ipmi_main.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  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 _XOPEN_SOURCE 700
  33. #define _BSD_SOURCE || \
  34. (_XOPEN_SOURCE >= 500 || \
  35. _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && \
  36. !(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600)
  37. #include <stdlib.h>
  38. #include <stdio.h>
  39. #include <inttypes.h>
  40. #include <signal.h>
  41. #include <string.h>
  42. #include <strings.h>
  43. #include <sys/types.h>
  44. #include <sys/stat.h>
  45. #include <unistd.h>
  46. #include <fcntl.h>
  47. #include <errno.h>
  48. #include <ctype.h>
  49. #include <ipmitool/helper.h>
  50. #include <ipmitool/log.h>
  51. #include <ipmitool/ipmi.h>
  52. #include <ipmitool/ipmi_intf.h>
  53. #include <ipmitool/ipmi_session.h>
  54. #include <ipmitool/ipmi_sdr.h>
  55. #include <ipmitool/ipmi_gendev.h>
  56. #include <ipmitool/ipmi_sel.h>
  57. #include <ipmitool/ipmi_fru.h>
  58. #include <ipmitool/ipmi_sol.h>
  59. #include <ipmitool/ipmi_isol.h>
  60. #include <ipmitool/ipmi_lanp.h>
  61. #include <ipmitool/ipmi_chassis.h>
  62. #include <ipmitool/ipmi_mc.h>
  63. #include <ipmitool/ipmi_firewall.h>
  64. #include <ipmitool/ipmi_sensor.h>
  65. #include <ipmitool/ipmi_channel.h>
  66. #include <ipmitool/ipmi_session.h>
  67. #include <ipmitool/ipmi_event.h>
  68. #include <ipmitool/ipmi_user.h>
  69. #include <ipmitool/ipmi_raw.h>
  70. #include <ipmitool/ipmi_pef.h>
  71. #include <ipmitool/ipmi_oem.h>
  72. #include <ipmitool/ipmi_ekanalyzer.h>
  73. #include <ipmitool/ipmi_picmg.h>
  74. #include <ipmitool/ipmi_kontronoem.h>
  75. #include <ipmitool/ipmi_vita.h>
  76. #ifdef HAVE_CONFIG_H
  77. # include <config.h>
  78. #endif
  79. #ifdef ENABLE_ALL_OPTIONS
  80. # define OPTION_STRING "I:46hVvcgsEKYao:H:d:P:f:U:p:C:L:A:t:T:m:z:S:l:b:B:e:k:y:O:R:N:D:"
  81. #else
  82. # define OPTION_STRING "I:46hVvcH:f:U:p:d:S:D:"
  83. #endif
  84. /* From src/plugins/ipmi_intf.c: */
  85. void
  86. ipmi_intf_set_max_request_data_size(struct ipmi_intf * intf, uint16_t size);
  87. extern int verbose;
  88. extern int csv_output;
  89. extern const struct valstr ipmi_privlvl_vals[];
  90. extern const struct valstr ipmi_authtype_session_vals[];
  91. static struct ipmi_intf * ipmi_main_intf = NULL;
  92. /* ipmi_password_file_read - Open file and read password from it
  93. *
  94. * @filename: file name to read from
  95. *
  96. * returns pointer to allocated buffer containing password
  97. * (caller is expected to free when finished)
  98. * returns NULL on error
  99. */
  100. static char *
  101. ipmi_password_file_read(char * filename)
  102. {
  103. FILE * fp;
  104. char * pass = NULL;
  105. int l;
  106. pass = malloc(21);
  107. if (pass == NULL) {
  108. lprintf(LOG_ERR, "ipmitool: malloc failure");
  109. return NULL;
  110. }
  111. memset(pass, 0, 21);
  112. fp = ipmi_open_file_read((const char *)filename);
  113. if (fp == NULL) {
  114. lprintf(LOG_ERR, "Unable to open password file %s",
  115. filename);
  116. free(pass);
  117. return NULL;
  118. }
  119. /* read in id */
  120. if (fgets(pass, 21, fp) == NULL) {
  121. lprintf(LOG_ERR, "Unable to read password from file %s",
  122. filename);
  123. free(pass);
  124. fclose(fp);
  125. return NULL;
  126. }
  127. /* remove traling <cr><nl><tab> */
  128. l = strcspn(pass, "\r\n\t");
  129. if (l > 0) {
  130. pass[l] = '\0';
  131. }
  132. fclose(fp);
  133. return pass;
  134. }
  135. /*
  136. * Print all the commands in the above table to stderr
  137. * used for help text on command line and shell
  138. */
  139. void
  140. ipmi_cmd_print(struct ipmi_cmd * cmdlist)
  141. {
  142. struct ipmi_cmd * cmd;
  143. int hdr = 0;
  144. if (cmdlist == NULL)
  145. return;
  146. for (cmd=cmdlist; cmd->func != NULL; cmd++) {
  147. if (cmd->desc == NULL)
  148. continue;
  149. if (hdr == 0) {
  150. lprintf(LOG_NOTICE, "Commands:");
  151. hdr = 1;
  152. }
  153. lprintf(LOG_NOTICE, "\t%-12s %s", cmd->name, cmd->desc);
  154. }
  155. lprintf(LOG_NOTICE, "");
  156. }
  157. /* ipmi_cmd_run - run a command from list based on parameters
  158. * called from main()
  159. *
  160. * 1. iterate through ipmi_cmd_list matching on name
  161. * 2. call func() for that command
  162. *
  163. * @intf: ipmi interface
  164. * @name: command name
  165. * @argc: command argument count
  166. * @argv: command argument list
  167. *
  168. * returns value from func() of that commnad if found
  169. * returns -1 if command is not found
  170. */
  171. int
  172. ipmi_cmd_run(struct ipmi_intf * intf, char * name, int argc, char ** argv)
  173. {
  174. struct ipmi_cmd * cmd = intf->cmdlist;
  175. /* hook to run a default command if nothing specified */
  176. if (name == NULL) {
  177. if (cmd->func == NULL || cmd->name == NULL)
  178. return -1;
  179. else if (strncmp(cmd->name, "default", 7) == 0)
  180. return cmd->func(intf, 0, NULL);
  181. else {
  182. lprintf(LOG_ERR, "No command provided!");
  183. ipmi_cmd_print(intf->cmdlist);
  184. return -1;
  185. }
  186. }
  187. for (cmd=intf->cmdlist; cmd->func != NULL; cmd++) {
  188. if (strncmp(name, cmd->name, __maxlen(cmd->name, name)) == 0)
  189. break;
  190. }
  191. if (cmd->func == NULL) {
  192. cmd = intf->cmdlist;
  193. if (strncmp(cmd->name, "default", 7) == 0)
  194. return cmd->func(intf, argc+1, argv-1);
  195. lprintf(LOG_ERR, "Invalid command: %s", name);
  196. ipmi_cmd_print(intf->cmdlist);
  197. return -1;
  198. }
  199. return cmd->func(intf, argc, argv);
  200. }
  201. static void
  202. ipmi_option_usage(const char * progname, struct ipmi_cmd * cmdlist, struct ipmi_intf_support * intflist)
  203. {
  204. lprintf(LOG_NOTICE, "%s version %s\n", progname, VERSION);
  205. lprintf(LOG_NOTICE, "usage: %s [options...] <command>\n", progname);
  206. lprintf(LOG_NOTICE, " -h This help");
  207. lprintf(LOG_NOTICE, " -V Show version information");
  208. lprintf(LOG_NOTICE, " -v Verbose (can use multiple times)");
  209. lprintf(LOG_NOTICE, " -c Display output in comma separated format");
  210. lprintf(LOG_NOTICE, " -d N Specify a /dev/ipmiN device to use (default=0)");
  211. lprintf(LOG_NOTICE, " -I intf Interface to use");
  212. lprintf(LOG_NOTICE, " -H hostname Remote host name for LAN interface");
  213. lprintf(LOG_NOTICE, " -p port Remote RMCP port [default=623]");
  214. lprintf(LOG_NOTICE, " -U username Remote session username");
  215. lprintf(LOG_NOTICE, " -f file Read remote session password from file");
  216. lprintf(LOG_NOTICE, " -z size Change Size of Communication Channel (OEM)");
  217. lprintf(LOG_NOTICE, " -S sdr Use local file for remote SDR cache");
  218. lprintf(LOG_NOTICE, " -D tty:b[:s] Specify the serial device, baud rate to use");
  219. lprintf(LOG_NOTICE, " and, optionally, specify that interface is the system one");
  220. lprintf(LOG_NOTICE, " -4 Use only IPv4");
  221. lprintf(LOG_NOTICE, " -6 Use only IPv6");
  222. #ifdef ENABLE_ALL_OPTIONS
  223. lprintf(LOG_NOTICE, " -a Prompt for remote password");
  224. lprintf(LOG_NOTICE, " -Y Prompt for the Kg key for IPMIv2 authentication");
  225. lprintf(LOG_NOTICE, " -e char Set SOL escape character");
  226. lprintf(LOG_NOTICE, " -C ciphersuite Cipher suite to be used by lanplus interface");
  227. lprintf(LOG_NOTICE, " -k key Use Kg key for IPMIv2 authentication");
  228. lprintf(LOG_NOTICE, " -y hex_key Use hexadecimal-encoded Kg key for IPMIv2 authentication");
  229. lprintf(LOG_NOTICE, " -L level Remote session privilege level [default=ADMINISTRATOR]");
  230. lprintf(LOG_NOTICE, " Append a '+' to use name/privilege lookup in RAKP1");
  231. lprintf(LOG_NOTICE, " -A authtype Force use of auth type NONE, PASSWORD, MD2, MD5 or OEM");
  232. lprintf(LOG_NOTICE, " -P password Remote session password");
  233. lprintf(LOG_NOTICE, " -E Read password from IPMI_PASSWORD environment variable");
  234. lprintf(LOG_NOTICE, " -K Read kgkey from IPMI_KGKEY environment variable");
  235. lprintf(LOG_NOTICE, " -m address Set local IPMB address");
  236. lprintf(LOG_NOTICE, " -b channel Set destination channel for bridged request");
  237. lprintf(LOG_NOTICE, " -t address Bridge request to remote target address");
  238. lprintf(LOG_NOTICE, " -B channel Set transit channel for bridged request (dual bridge)");
  239. lprintf(LOG_NOTICE, " -T address Set transit address for bridge request (dual bridge)");
  240. lprintf(LOG_NOTICE, " -l lun Set destination lun for raw commands");
  241. lprintf(LOG_NOTICE, " -o oemtype Setup for OEM (use 'list' to see available OEM types)");
  242. lprintf(LOG_NOTICE, " -O seloem Use file for OEM SEL event descriptions");
  243. lprintf(LOG_NOTICE, " -N seconds Specify timeout for lan [default=2] / lanplus [default=1] interface");
  244. lprintf(LOG_NOTICE, " -R retry Set the number of retries for lan/lanplus interface [default=4]");
  245. #endif
  246. lprintf(LOG_NOTICE, "");
  247. ipmi_intf_print(intflist);
  248. if (cmdlist != NULL)
  249. ipmi_cmd_print(cmdlist);
  250. }
  251. /* ipmi_catch_sigint - Handle the interrupt signal (Ctrl-C), close the
  252. * interface, and exit ipmitool with error (-1)
  253. *
  254. * This insures that the IOL session gets freed
  255. * for other callers.
  256. *
  257. * returns -1
  258. */
  259. void ipmi_catch_sigint()
  260. {
  261. if (ipmi_main_intf != NULL) {
  262. printf("\nSIGN INT: Close Interface %s\n",ipmi_main_intf->desc);
  263. /* reduce retry count to a single retry */
  264. ipmi_main_intf->ssn_params.retry = 1;
  265. /* close interface */
  266. ipmi_main_intf->close(ipmi_main_intf);
  267. }
  268. exit(-1);
  269. }
  270. static uint8_t
  271. ipmi_acquire_ipmb_address(struct ipmi_intf * intf)
  272. {
  273. if (intf->picmg_avail) {
  274. return ipmi_picmg_ipmb_address(intf);
  275. } else if (intf->vita_avail) {
  276. return ipmi_vita_ipmb_address(intf);
  277. } else {
  278. return 0;
  279. }
  280. }
  281. /* ipmi_parse_options - helper function to handle parsing command line options
  282. *
  283. * @argc: count of options
  284. * @argv: list of options
  285. * @cmdlist: list of supported commands
  286. * @intflist: list of supported interfaces
  287. *
  288. * returns 0 on success
  289. * returns -1 on error
  290. */
  291. int
  292. ipmi_main(int argc, char ** argv,
  293. struct ipmi_cmd * cmdlist,
  294. struct ipmi_intf_support * intflist)
  295. {
  296. struct ipmi_intf_support * sup;
  297. int privlvl = 0;
  298. uint8_t target_addr = 0;
  299. uint8_t target_channel = 0;
  300. uint8_t transit_addr = 0;
  301. uint8_t transit_channel = 0;
  302. uint8_t target_lun = 0;
  303. uint8_t arg_addr = 0;
  304. uint8_t addr = 0;
  305. uint16_t my_long_packet_size=0;
  306. uint8_t my_long_packet_set=0;
  307. uint8_t lookupbit = 0x10; /* use name-only lookup by default */
  308. int retry = 0;
  309. uint32_t timeout = 0;
  310. int authtype = -1;
  311. char * tmp_pass = NULL;
  312. char * tmp_env = NULL;
  313. char * hostname = NULL;
  314. char * username = NULL;
  315. char * password = NULL;
  316. char * intfname = NULL;
  317. char * progname = NULL;
  318. char * oemtype = NULL;
  319. char * sdrcache = NULL;
  320. uint8_t kgkey[IPMI_KG_BUFFER_SIZE];
  321. char * seloem = NULL;
  322. int port = 0;
  323. int devnum = 0;
  324. int cipher_suite_id = 3; /* See table 22-19 of the IPMIv2 spec */
  325. int argflag, i, found;
  326. int rc = -1;
  327. int ai_family = AF_UNSPEC;
  328. char sol_escape_char = SOL_ESCAPE_CHARACTER_DEFAULT;
  329. char * devfile = NULL;
  330. /* save program name */
  331. progname = strrchr(argv[0], '/');
  332. progname = ((progname == NULL) ? argv[0] : progname+1);
  333. signal(SIGINT, ipmi_catch_sigint);
  334. memset(kgkey, 0, sizeof(kgkey));
  335. while ((argflag = getopt(argc, (char **)argv, OPTION_STRING)) != -1)
  336. {
  337. switch (argflag) {
  338. case 'I':
  339. if (intfname) {
  340. free(intfname);
  341. intfname = NULL;
  342. }
  343. intfname = strdup(optarg);
  344. if (intfname == NULL) {
  345. lprintf(LOG_ERR, "%s: malloc failure", progname);
  346. goto out_free;
  347. }
  348. if (intflist != NULL) {
  349. found = 0;
  350. for (sup=intflist; sup->name != NULL; sup++) {
  351. if (strncmp(sup->name, intfname, strlen(intfname)) == 0 &&
  352. strncmp(sup->name, intfname, strlen(sup->name)) == 0 &&
  353. sup->supported == 1)
  354. found = 1;
  355. }
  356. if (!found) {
  357. lprintf(LOG_ERR, "Interface %s not supported", intfname);
  358. goto out_free;
  359. }
  360. }
  361. break;
  362. case 'h':
  363. ipmi_option_usage(progname, cmdlist, intflist);
  364. rc = 0;
  365. goto out_free;
  366. break;
  367. case 'V':
  368. printf("%s version %s\n", progname, VERSION);
  369. rc = 0;
  370. goto out_free;
  371. break;
  372. case 'd':
  373. if (str2int(optarg, &devnum) != 0) {
  374. lprintf(LOG_ERR, "Invalid parameter given or out of range for '-d'.");
  375. rc = -1;
  376. goto out_free;
  377. }
  378. /* Check if device number is -gt 0; I couldn't find limit for
  379. * kernels > 2.6, thus right side is unlimited.
  380. */
  381. if (devnum < 0) {
  382. lprintf(LOG_ERR, "Device number %i is out of range.", devnum);
  383. rc = -1;
  384. goto out_free;
  385. }
  386. break;
  387. case 'p':
  388. if (str2int(optarg, &port) != 0) {
  389. lprintf(LOG_ERR, "Invalid parameter given or out of range for '-p'.");
  390. rc = -1;
  391. goto out_free;
  392. }
  393. /* Check if port is -gt 0 && port is -lt 65535 */
  394. if (port < 0 || port > 65535) {
  395. lprintf(LOG_ERR, "Port number %i is out of range.", port);
  396. rc = -1;
  397. goto out_free;
  398. }
  399. break;
  400. case 'C':
  401. if (str2int(optarg, &cipher_suite_id) != 0) {
  402. lprintf(LOG_ERR, "Invalid parameter given or out of range for '-C'.");
  403. rc = -1;
  404. goto out_free;
  405. }
  406. /* add check Cipher is -gt 0 */
  407. if (cipher_suite_id < 0) {
  408. lprintf(LOG_ERR, "Cipher suite ID %i is invalid.", cipher_suite_id);
  409. rc = -1;
  410. goto out_free;
  411. }
  412. break;
  413. case 'v':
  414. verbose++;
  415. break;
  416. case 'c':
  417. csv_output = 1;
  418. break;
  419. case 'H':
  420. if (hostname) {
  421. free(hostname);
  422. hostname = NULL;
  423. }
  424. hostname = strdup(optarg);
  425. if (hostname == NULL) {
  426. lprintf(LOG_ERR, "%s: malloc failure", progname);
  427. goto out_free;
  428. }
  429. break;
  430. case 'f':
  431. if (password) {
  432. free(password);
  433. password = NULL;
  434. }
  435. password = ipmi_password_file_read(optarg);
  436. if (password == NULL)
  437. lprintf(LOG_ERR, "Unable to read password "
  438. "from file %s", optarg);
  439. break;
  440. case 'a':
  441. #ifdef HAVE_GETPASSPHRASE
  442. tmp_pass = getpassphrase("Password: ");
  443. #else
  444. tmp_pass = getpass("Password: ");
  445. #endif
  446. if (tmp_pass != NULL) {
  447. if (password) {
  448. free(password);
  449. password = NULL;
  450. }
  451. password = strdup(tmp_pass);
  452. tmp_pass = NULL;
  453. if (password == NULL) {
  454. lprintf(LOG_ERR, "%s: malloc failure", progname);
  455. goto out_free;
  456. }
  457. }
  458. break;
  459. case 'k':
  460. memset(kgkey, 0, sizeof(kgkey));
  461. strncpy((char *)kgkey, optarg, sizeof(kgkey) - 1);
  462. break;
  463. case 'K':
  464. if ((tmp_env = getenv("IPMI_KGKEY"))) {
  465. memset(kgkey, 0, sizeof(kgkey));
  466. strncpy((char *)kgkey, tmp_env,
  467. sizeof(kgkey) - 1);
  468. } else {
  469. lprintf(LOG_WARN, "Unable to read kgkey from environment");
  470. }
  471. break;
  472. case 'y':
  473. memset(kgkey, 0, sizeof(kgkey));
  474. rc = ipmi_parse_hex(optarg, kgkey, sizeof(kgkey) - 1);
  475. if (rc == -1) {
  476. lprintf(LOG_ERR, "Number of Kg key characters is not even");
  477. goto out_free;
  478. } else if (rc == -3) {
  479. lprintf(LOG_ERR, "Kg key is not hexadecimal number");
  480. goto out_free;
  481. } else if (rc > (IPMI_KG_BUFFER_SIZE-1)) {
  482. lprintf(LOG_ERR, "Kg key is too long");
  483. goto out_free;
  484. }
  485. break;
  486. case 'Y':
  487. #ifdef HAVE_GETPASSPHRASE
  488. tmp_pass = getpassphrase("Key: ");
  489. #else
  490. tmp_pass = getpass("Key: ");
  491. #endif
  492. if (tmp_pass != NULL) {
  493. memset(kgkey, 0, sizeof(kgkey));
  494. strncpy((char *)kgkey, tmp_pass,
  495. sizeof(kgkey) - 1);
  496. tmp_pass = NULL;
  497. }
  498. break;
  499. case 'U':
  500. if (username) {
  501. free(username);
  502. username = NULL;
  503. }
  504. if (strlen(optarg) > 16) {
  505. lprintf(LOG_ERR, "Username is too long (> 16 bytes)");
  506. goto out_free;
  507. }
  508. username = strdup(optarg);
  509. if (username == NULL) {
  510. lprintf(LOG_ERR, "%s: malloc failure", progname);
  511. goto out_free;
  512. }
  513. break;
  514. case 'S':
  515. if (sdrcache) {
  516. free(sdrcache);
  517. sdrcache = NULL;
  518. }
  519. sdrcache = strdup(optarg);
  520. if (sdrcache == NULL) {
  521. lprintf(LOG_ERR, "%s: malloc failure", progname);
  522. goto out_free;
  523. }
  524. break;
  525. case 'D':
  526. /* check for subsequent instance of -D */
  527. if (devfile) {
  528. /* free memory for previous string */
  529. free(devfile);
  530. }
  531. devfile = strdup(optarg);
  532. if (devfile == NULL) {
  533. lprintf(LOG_ERR, "%s: malloc failure", progname);
  534. goto out_free;
  535. }
  536. break;
  537. case '4':
  538. /* IPv4 only */
  539. if (ai_family == AF_UNSPEC) {
  540. ai_family = AF_INET;
  541. } else {
  542. if (ai_family == AF_INET6) {
  543. lprintf(LOG_ERR,
  544. "Parameter is mutually exclusive with -6.");
  545. } else {
  546. lprintf(LOG_ERR,
  547. "Multiple -4 parameters given.");
  548. }
  549. rc = (-1);
  550. goto out_free;
  551. }
  552. break;
  553. case '6':
  554. /* IPv6 only */
  555. if (ai_family == AF_UNSPEC) {
  556. ai_family = AF_INET6;
  557. } else {
  558. if (ai_family == AF_INET) {
  559. lprintf(LOG_ERR,
  560. "Parameter is mutually exclusive with -4.");
  561. } else {
  562. lprintf(LOG_ERR,
  563. "Multiple -6 parameters given.");
  564. }
  565. rc = (-1);
  566. goto out_free;
  567. }
  568. break;
  569. #ifdef ENABLE_ALL_OPTIONS
  570. case 'o':
  571. if (oemtype) {
  572. free(oemtype);
  573. oemtype = NULL;
  574. }
  575. oemtype = strdup(optarg);
  576. if (oemtype == NULL) {
  577. lprintf(LOG_ERR, "%s: malloc failure", progname);
  578. goto out_free;
  579. }
  580. if (strncmp(oemtype, "list", 4) == 0 ||
  581. strncmp(oemtype, "help", 4) == 0) {
  582. ipmi_oem_print();
  583. rc = 0;
  584. goto out_free;
  585. }
  586. break;
  587. case 'g':
  588. /* backwards compatible oem hack */
  589. if (oemtype) {
  590. free(oemtype);
  591. oemtype = NULL;
  592. }
  593. oemtype = strdup("intelwv2");
  594. break;
  595. case 's':
  596. /* backwards compatible oem hack */
  597. if (oemtype) {
  598. free(oemtype);
  599. oemtype = NULL;
  600. }
  601. oemtype = strdup("supermicro");
  602. break;
  603. case 'P':
  604. if (password) {
  605. free(password);
  606. password = NULL;
  607. }
  608. password = strdup(optarg);
  609. if (password == NULL) {
  610. lprintf(LOG_ERR, "%s: malloc failure", progname);
  611. goto out_free;
  612. }
  613. /* Prevent password snooping with ps */
  614. i = strlen(optarg);
  615. memset(optarg, 'X', i);
  616. break;
  617. case 'E':
  618. if ((tmp_env = getenv("IPMITOOL_PASSWORD"))) {
  619. if (password) {
  620. free(password);
  621. password = NULL;
  622. }
  623. password = strdup(tmp_env);
  624. if (password == NULL) {
  625. lprintf(LOG_ERR, "%s: malloc failure", progname);
  626. goto out_free;
  627. }
  628. }
  629. else if ((tmp_env = getenv("IPMI_PASSWORD"))) {
  630. if (password) {
  631. free(password);
  632. password = NULL;
  633. }
  634. password = strdup(tmp_env);
  635. if (password == NULL) {
  636. lprintf(LOG_ERR, "%s: malloc failure", progname);
  637. goto out_free;
  638. }
  639. }
  640. else {
  641. lprintf(LOG_WARN, "Unable to read password from environment");
  642. }
  643. break;
  644. case 'L':
  645. i = strlen(optarg);
  646. if ((i > 0) && (optarg[i-1] == '+')) {
  647. lookupbit = 0;
  648. optarg[i-1] = 0;
  649. }
  650. privlvl = str2val(optarg, ipmi_privlvl_vals);
  651. if (privlvl == 0xFF) {
  652. lprintf(LOG_WARN, "Invalid privilege level %s", optarg);
  653. }
  654. break;
  655. case 'A':
  656. authtype = str2val(optarg, ipmi_authtype_session_vals);
  657. break;
  658. case 't':
  659. if (str2uchar(optarg, &target_addr) != 0) {
  660. lprintf(LOG_ERR, "Invalid parameter given or out of range for '-t'.");
  661. rc = -1;
  662. goto out_free;
  663. }
  664. break;
  665. case 'b':
  666. if (str2uchar(optarg, &target_channel) != 0) {
  667. lprintf(LOG_ERR, "Invalid parameter given or out of range for '-b'.");
  668. rc = -1;
  669. goto out_free;
  670. }
  671. break;
  672. case 'T':
  673. if (str2uchar(optarg, &transit_addr) != 0) {
  674. lprintf(LOG_ERR, "Invalid parameter given or out of range for '-T'.");
  675. rc = -1;
  676. goto out_free;
  677. }
  678. break;
  679. case 'B':
  680. if (str2uchar(optarg, &transit_channel) != 0) {
  681. lprintf(LOG_ERR, "Invalid parameter given or out of range for '-B'.");
  682. rc = -1;
  683. goto out_free;
  684. }
  685. break;
  686. case 'l':
  687. if (str2uchar(optarg, &target_lun) != 0) {
  688. lprintf(LOG_ERR, "Invalid parameter given or out of range for '-l'.");
  689. rc = 1;
  690. goto out_free;
  691. }
  692. break;
  693. case 'm':
  694. if (str2uchar(optarg, &arg_addr) != 0) {
  695. lprintf(LOG_ERR, "Invalid parameter given or out of range for '-m'.");
  696. rc = -1;
  697. goto out_free;
  698. }
  699. break;
  700. case 'e':
  701. sol_escape_char = optarg[0];
  702. break;
  703. case 'O':
  704. if (seloem) {
  705. free(seloem);
  706. seloem = NULL;
  707. }
  708. seloem = strdup(optarg);
  709. if (seloem == NULL) {
  710. lprintf(LOG_ERR, "%s: malloc failure", progname);
  711. goto out_free;
  712. }
  713. break;
  714. case 'z':
  715. if (str2ushort(optarg, &my_long_packet_size) != 0) {
  716. lprintf(LOG_ERR, "Invalid parameter given or out of range for '-z'.");
  717. rc = -1;
  718. goto out_free;
  719. }
  720. break;
  721. /* Retry and Timeout */
  722. case 'R':
  723. if (str2int(optarg, &retry) != 0 || retry < 0) {
  724. lprintf(LOG_ERR, "Invalid parameter given or out of range for '-R'.");
  725. rc = -1;
  726. goto out_free;
  727. }
  728. break;
  729. case 'N':
  730. if (str2uint(optarg, &timeout) != 0) {
  731. lprintf(LOG_ERR, "Invalid parameter given or out of range for '-N'.");
  732. rc = -1;
  733. goto out_free;
  734. }
  735. break;
  736. #endif
  737. default:
  738. ipmi_option_usage(progname, cmdlist, intflist);
  739. goto out_free;
  740. }
  741. }
  742. /* check for command before doing anything */
  743. if (argc-optind > 0 &&
  744. strncmp(argv[optind], "help", 4) == 0) {
  745. ipmi_cmd_print(cmdlist);
  746. rc = 0;
  747. goto out_free;
  748. }
  749. /*
  750. * If the user has specified a hostname (-H option)
  751. * then this is a remote access session.
  752. *
  753. * If no password was specified by any other method
  754. * and the authtype was not explicitly set to NONE
  755. * then prompt the user.
  756. */
  757. if (hostname != NULL && password == NULL &&
  758. (authtype != IPMI_SESSION_AUTHTYPE_NONE || authtype < 0)) {
  759. #ifdef HAVE_GETPASSPHRASE
  760. tmp_pass = getpassphrase("Password: ");
  761. #else
  762. tmp_pass = getpass("Password: ");
  763. #endif
  764. if (tmp_pass != NULL) {
  765. password = strdup(tmp_pass);
  766. tmp_pass = NULL;
  767. if (password == NULL) {
  768. lprintf(LOG_ERR, "%s: malloc failure", progname);
  769. goto out_free;
  770. }
  771. }
  772. }
  773. /* if no interface was specified but a
  774. * hostname was then use LAN by default
  775. * otherwise the default is hardcoded
  776. * to use the first entry in the list
  777. */
  778. if (intfname == NULL && hostname != NULL) {
  779. intfname = strdup("lan");
  780. if (intfname == NULL) {
  781. lprintf(LOG_ERR, "%s: malloc failure", progname);
  782. goto out_free;
  783. }
  784. }
  785. if (password != NULL && intfname != NULL) {
  786. if (strcmp(intfname, "lan") == 0 && strlen(password) > 16) {
  787. lprintf(LOG_ERR, "%s: password is longer than 16 bytes.", intfname);
  788. rc = -1;
  789. goto out_free;
  790. } else if (strcmp(intfname, "lanplus") == 0 && strlen(password) > 20) {
  791. lprintf(LOG_ERR, "%s: password is longer than 20 bytes.", intfname);
  792. rc = -1;
  793. goto out_free;
  794. }
  795. } /* if (password != NULL && intfname != NULL) */
  796. /* load interface */
  797. ipmi_main_intf = ipmi_intf_load(intfname);
  798. if (ipmi_main_intf == NULL) {
  799. lprintf(LOG_ERR, "Error loading interface %s", intfname);
  800. goto out_free;
  801. }
  802. /* setup log */
  803. log_init(progname, 0, verbose);
  804. /* run OEM setup if found */
  805. if (oemtype != NULL &&
  806. ipmi_oem_setup(ipmi_main_intf, oemtype) < 0) {
  807. lprintf(LOG_ERR, "OEM setup for \"%s\" failed", oemtype);
  808. goto out_free;
  809. }
  810. /* set session variables */
  811. if (hostname != NULL)
  812. ipmi_intf_session_set_hostname(ipmi_main_intf, hostname);
  813. if (username != NULL)
  814. ipmi_intf_session_set_username(ipmi_main_intf, username);
  815. if (password != NULL)
  816. ipmi_intf_session_set_password(ipmi_main_intf, password);
  817. ipmi_intf_session_set_kgkey(ipmi_main_intf, kgkey);
  818. if (port > 0)
  819. ipmi_intf_session_set_port(ipmi_main_intf, port);
  820. if (authtype >= 0)
  821. ipmi_intf_session_set_authtype(ipmi_main_intf, (uint8_t)authtype);
  822. if (privlvl > 0)
  823. ipmi_intf_session_set_privlvl(ipmi_main_intf, (uint8_t)privlvl);
  824. else
  825. ipmi_intf_session_set_privlvl(ipmi_main_intf,
  826. IPMI_SESSION_PRIV_ADMIN); /* default */
  827. /* Adding retry and timeout for interface that support it */
  828. if (retry > 0)
  829. ipmi_intf_session_set_retry(ipmi_main_intf, retry);
  830. if (timeout > 0)
  831. ipmi_intf_session_set_timeout(ipmi_main_intf, timeout);
  832. ipmi_intf_session_set_lookupbit(ipmi_main_intf, lookupbit);
  833. ipmi_intf_session_set_sol_escape_char(ipmi_main_intf, sol_escape_char);
  834. ipmi_intf_session_set_cipher_suite_id(ipmi_main_intf, cipher_suite_id);
  835. ipmi_main_intf->devnum = devnum;
  836. /* setup device file if given */
  837. ipmi_main_intf->devfile = devfile;
  838. ipmi_main_intf->ai_family = ai_family;
  839. /* Open the interface with the specified or default IPMB address */
  840. ipmi_main_intf->my_addr = arg_addr ? arg_addr : IPMI_BMC_SLAVE_ADDR;
  841. if (ipmi_main_intf->open != NULL) {
  842. if (ipmi_main_intf->open(ipmi_main_intf) < 0) {
  843. goto out_free;
  844. }
  845. }
  846. // jimbo comment
  847. // if (!ipmi_oem_active(ipmi_main_intf, "i82571spt")) {
  848. // /*
  849. // * Attempt picmg/vita discovery of the actual interface
  850. // * address, unless the users specified an address.
  851. // * Address specification always overrides discovery
  852. // */
  853. // if (picmg_discover(ipmi_main_intf)) {
  854. // ipmi_main_intf->picmg_avail = 1;
  855. // } else if (vita_discover(ipmi_main_intf)) {
  856. // ipmi_main_intf->vita_avail = 1;
  857. // }
  858. // }
  859. if (arg_addr) {
  860. addr = arg_addr;
  861. } else if (!ipmi_oem_active(ipmi_main_intf, "i82571spt")) {
  862. lprintf(LOG_DEBUG, "Acquire IPMB address");
  863. addr = ipmi_acquire_ipmb_address(ipmi_main_intf);
  864. lprintf(LOG_INFO, "Discovered IPMB address 0x%x", addr);
  865. }
  866. /*
  867. * If we discovered the ipmb address and it is not the same as what we
  868. * used for open, Set the discovered IPMB address as my address if the
  869. * interface supports it.
  870. */
  871. if (addr != 0 && addr != ipmi_main_intf->my_addr) {
  872. if (ipmi_main_intf->set_my_addr) {
  873. /*
  874. * Some interfaces need special handling
  875. * when changing local address
  876. */
  877. (void)ipmi_main_intf->set_my_addr(ipmi_main_intf, addr);
  878. }
  879. /* set local address */
  880. ipmi_main_intf->my_addr = addr;
  881. }
  882. ipmi_main_intf->target_addr = ipmi_main_intf->my_addr;
  883. /* If bridging addresses are specified, handle them */
  884. if (transit_addr > 0 || target_addr > 0) {
  885. /* sanity check, transit makes no sense without a target */
  886. if ((transit_addr != 0 || transit_channel != 0) &&
  887. target_addr == 0) {
  888. lprintf(LOG_ERR,
  889. "Transit address/channel %#x/%#x ignored. "
  890. "Target address must be specified!",
  891. transit_addr, transit_channel);
  892. goto out_free;
  893. }
  894. ipmi_main_intf->target_addr = target_addr;
  895. ipmi_main_intf->target_channel = target_channel ;
  896. ipmi_main_intf->transit_addr = transit_addr;
  897. ipmi_main_intf->transit_channel = transit_channel;
  898. /* must be admin level to do this over lan */
  899. ipmi_intf_session_set_privlvl(ipmi_main_intf, IPMI_SESSION_PRIV_ADMIN);
  900. /* Get the ipmb address of the targeted entity */
  901. ipmi_main_intf->target_ipmb_addr =
  902. ipmi_acquire_ipmb_address(ipmi_main_intf);
  903. lprintf(LOG_DEBUG, "Specified addressing Target %#x:%#x Transit %#x:%#x",
  904. ipmi_main_intf->target_addr,
  905. ipmi_main_intf->target_channel,
  906. ipmi_main_intf->transit_addr,
  907. ipmi_main_intf->transit_channel);
  908. if (ipmi_main_intf->target_ipmb_addr) {
  909. lprintf(LOG_INFO, "Discovered Target IPMB-0 address %#x",
  910. ipmi_main_intf->target_ipmb_addr);
  911. }
  912. }
  913. /* set target LUN (for RAW command) */
  914. ipmi_main_intf->target_lun = target_lun ;
  915. lprintf(LOG_DEBUG, "Interface address: my_addr %#x "
  916. "transit %#x:%#x target %#x:%#x "
  917. "ipmb_target %#x\n",
  918. ipmi_main_intf->my_addr,
  919. ipmi_main_intf->transit_addr,
  920. ipmi_main_intf->transit_channel,
  921. ipmi_main_intf->target_addr,
  922. ipmi_main_intf->target_channel,
  923. ipmi_main_intf->target_ipmb_addr);
  924. /* parse local SDR cache if given */
  925. if (sdrcache != NULL) {
  926. ipmi_sdr_list_cache_fromfile(ipmi_main_intf, sdrcache);
  927. }
  928. /* Parse SEL OEM file if given */
  929. if (seloem != NULL) {
  930. ipmi_sel_oem_init(seloem);
  931. }
  932. /* Enable Big Buffer when requested */
  933. if ( my_long_packet_size != 0 ) {
  934. /* Enable Big Buffer when requested */
  935. if (!ipmi_oem_active(ipmi_main_intf, "kontron") ||
  936. ipmi_kontronoem_set_large_buffer(ipmi_main_intf,
  937. my_long_packet_size ) == 0) {
  938. printf("Setting large buffer to %i\n", my_long_packet_size);
  939. my_long_packet_set = 1;
  940. ipmi_intf_set_max_request_data_size(ipmi_main_intf,
  941. my_long_packet_size);
  942. }
  943. }
  944. ipmi_main_intf->cmdlist = cmdlist;
  945. /* now we finally run the command */
  946. if (argc-optind > 0)
  947. rc = ipmi_cmd_run(ipmi_main_intf, argv[optind], argc-optind-1,
  948. &(argv[optind+1]));
  949. else
  950. rc = ipmi_cmd_run(ipmi_main_intf, NULL, 0, NULL);
  951. if (my_long_packet_set == 1) {
  952. if (ipmi_oem_active(ipmi_main_intf, "kontron")) {
  953. /* Restore defaults */
  954. ipmi_kontronoem_set_large_buffer( ipmi_main_intf, 0 );
  955. }
  956. }
  957. /* clean repository caches */
  958. ipmi_cleanup(ipmi_main_intf);
  959. /* call interface close function if available */
  960. if (ipmi_main_intf->opened > 0 && ipmi_main_intf->close != NULL)
  961. ipmi_main_intf->close(ipmi_main_intf);
  962. out_free:
  963. log_halt();
  964. if (intfname != NULL) {
  965. free(intfname);
  966. intfname = NULL;
  967. }
  968. if (hostname != NULL) {
  969. free(hostname);
  970. hostname = NULL;
  971. }
  972. if (username != NULL) {
  973. free(username);
  974. username = NULL;
  975. }
  976. if (password != NULL) {
  977. free(password);
  978. password = NULL;
  979. }
  980. if (oemtype != NULL) {
  981. free(oemtype);
  982. oemtype = NULL;
  983. }
  984. if (seloem != NULL) {
  985. free(seloem);
  986. seloem = NULL;
  987. }
  988. if (sdrcache != NULL) {
  989. free(sdrcache);
  990. sdrcache = NULL;
  991. }
  992. if (devfile) {
  993. free(devfile);
  994. devfile = NULL;
  995. }
  996. return rc;
  997. }