ipmi_isol.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  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
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <strings.h>
  36. #include <stdio.h>
  37. #include <sys/types.h>
  38. #include <sys/stat.h>
  39. #include <sys/select.h>
  40. #include <sys/time.h>
  41. #include <signal.h>
  42. #include <unistd.h>
  43. #include <termios.h>
  44. #include <ipmitool/helper.h>
  45. #include <ipmitool/log.h>
  46. #include <ipmitool/ipmi.h>
  47. #include <ipmitool/ipmi_strings.h>
  48. #include <ipmitool/ipmi_intf.h>
  49. #include <ipmitool/ipmi_isol.h>
  50. static struct termios _saved_tio;
  51. static int _in_raw_mode = 0;
  52. extern int verbose;
  53. #define ISOL_ESCAPE_CHARACTER '~'
  54. /*
  55. * ipmi_get_isol_info
  56. */
  57. static int ipmi_get_isol_info(struct ipmi_intf * intf,
  58. struct isol_config_parameters * params)
  59. {
  60. struct ipmi_rs * rsp;
  61. struct ipmi_rq req;
  62. unsigned char data[6];
  63. memset(&req, 0, sizeof(req));
  64. req.msg.netfn = IPMI_NETFN_ISOL;
  65. req.msg.cmd = GET_ISOL_CONFIG;
  66. req.msg.data = data;
  67. req.msg.data_len = 4;
  68. /* GET ISOL ENABLED CONFIG */
  69. memset(data, 0, 6);
  70. data[0] = 0x00;
  71. data[1] = ISOL_ENABLE_PARAM;
  72. data[2] = 0x00; /* block */
  73. data[3] = 0x00; /* selector */
  74. rsp = intf->sendrecv(intf, &req);
  75. if (rsp == NULL) {
  76. lprintf(LOG_ERR, "Error in Get ISOL Config Command");
  77. return -1;
  78. }
  79. if (rsp->ccode == 0xc1) {
  80. lprintf(LOG_ERR, "IPMI v1.5 Serial Over Lan (ISOL) not supported!");
  81. return -1;
  82. }
  83. if (rsp->ccode > 0) {
  84. lprintf(LOG_ERR, "Error in Get ISOL Config Command: %s",
  85. val2str(rsp->ccode, completion_code_vals));
  86. return -1;
  87. }
  88. params->enabled = rsp->data[1];
  89. /* GET ISOL AUTHENTICATON CONFIG */
  90. memset(data, 0, 6);
  91. data[0] = 0x00;
  92. data[1] = ISOL_AUTHENTICATION_PARAM;
  93. data[2] = 0x00; /* block */
  94. data[3] = 0x00; /* selector */
  95. rsp = intf->sendrecv(intf, &req);
  96. if (rsp == NULL) {
  97. lprintf(LOG_ERR, "Error in Get ISOL Config Command");
  98. return -1;
  99. }
  100. if (rsp->ccode > 0) {
  101. lprintf(LOG_ERR, "Error in Get ISOL Config Command: %s",
  102. val2str(rsp->ccode, completion_code_vals));
  103. return -1;
  104. }
  105. params->privilege_level = rsp->data[1];
  106. /* GET ISOL BAUD RATE CONFIG */
  107. memset(data, 0, 6);
  108. data[0] = 0x00;
  109. data[1] = ISOL_BAUD_RATE_PARAM;
  110. data[2] = 0x00; /* block */
  111. data[3] = 0x00; /* selector */
  112. rsp = intf->sendrecv(intf, &req);
  113. if (rsp == NULL) {
  114. lprintf(LOG_ERR, "Error in Get ISOL Config Command");
  115. return -1;
  116. }
  117. if (rsp->ccode > 0) {
  118. lprintf(LOG_ERR, "Error in Get ISOL Config Command: %s",
  119. val2str(rsp->ccode, completion_code_vals));
  120. return -1;
  121. }
  122. params->bit_rate = rsp->data[1];
  123. return 0;
  124. }
  125. static int ipmi_print_isol_info(struct ipmi_intf * intf)
  126. {
  127. struct isol_config_parameters params = {0};
  128. if (ipmi_get_isol_info(intf, &params))
  129. return -1;
  130. if (csv_output)
  131. {
  132. printf("%s,", (params.enabled & 0x1)?"true": "false");
  133. printf("%s,",
  134. val2str((params.privilege_level & 0xf), ipmi_privlvl_vals));
  135. printf("%s,",
  136. val2str((params.bit_rate & 0xf), ipmi_bit_rate_vals));
  137. }
  138. else
  139. {
  140. printf("Enabled : %s\n",
  141. (params.enabled & 0x1)?"true": "false");
  142. printf("Privilege Level : %s\n",
  143. val2str((params.privilege_level & 0xf), ipmi_privlvl_vals));
  144. printf("Bit Rate (kbps) : %s\n",
  145. val2str((params.bit_rate & 0xf), ipmi_bit_rate_vals));
  146. }
  147. return 0;
  148. }
  149. static int ipmi_isol_set_param(struct ipmi_intf * intf,
  150. const char *param,
  151. const char *value)
  152. {
  153. struct ipmi_rs * rsp;
  154. struct ipmi_rq req;
  155. unsigned char data[6];
  156. struct isol_config_parameters params = {0};
  157. /* We need other values to complete the request */
  158. if (ipmi_get_isol_info(intf, &params))
  159. return -1;
  160. memset(&req, 0, sizeof(req));
  161. req.msg.netfn = IPMI_NETFN_ISOL;
  162. req.msg.cmd = SET_ISOL_CONFIG;
  163. req.msg.data = data;
  164. req.msg.data_len = 3;
  165. memset(data, 0, 6);
  166. /*
  167. * enabled
  168. */
  169. if (strcmp(param, "enabled") == 0)
  170. {
  171. data[1] = ISOL_ENABLE_PARAM;
  172. if (strcmp(value, "true") == 0)
  173. data[2] = 0x01;
  174. else if (strcmp(value, "false") == 0)
  175. data[2] = 0x00;
  176. else {
  177. lprintf(LOG_ERR, "Invalid value %s for parameter %s",
  178. value, param);
  179. lprintf(LOG_ERR, "Valid values are true and false");
  180. return -1;
  181. }
  182. }
  183. /*
  184. * privilege-level
  185. */
  186. else if (strcmp(param, "privilege-level") == 0)
  187. {
  188. data[1] = ISOL_AUTHENTICATION_PARAM;
  189. if (! strcmp(value, "user"))
  190. data[2] = 0x02;
  191. else if (! strcmp(value, "operator"))
  192. data[2] = 0x03;
  193. else if (! strcmp(value, "admin"))
  194. data[2] = 0x04;
  195. else if (! strcmp(value, "oem"))
  196. data[2] = 0x05;
  197. else
  198. {
  199. lprintf(LOG_ERR, "Invalid value %s for parameter %s",
  200. value, param);
  201. lprintf(LOG_ERR, "Valid values are user, operator, admin, and oem");
  202. return -1;
  203. }
  204. /* We need to mask bit7 from the fetched value */
  205. data[2] |= (params.privilege_level & 0x80) ? 0x80 : 0x00;
  206. }
  207. /*
  208. * bit-rate
  209. */
  210. else if (strcmp(param, "bit-rate") == 0)
  211. {
  212. data[1] = ISOL_BAUD_RATE_PARAM;
  213. if (strncmp(value, "9.6", 3) == 0) {
  214. data[2] = 0x06;
  215. }
  216. else if (strncmp(value, "19.2", 4) == 0) {
  217. data[2] = 0x07;
  218. }
  219. else if (strncmp(value, "38.4", 4) == 0) {
  220. data[2] = 0x08;
  221. }
  222. else if (strncmp(value, "57.6", 4) == 0) {
  223. data[2] = 0x09;
  224. }
  225. else if (strncmp(value, "115.2", 5) == 0) {
  226. data[2] = 0x0A;
  227. }
  228. else {
  229. lprintf(LOG_ERR, "ISOL - Unsupported baud rate: %s", value);
  230. lprintf(LOG_ERR, "Valid values are 9.6, 19.2, 38.4, 57.6 and 115.2");
  231. return -1;
  232. }
  233. }
  234. else
  235. {
  236. lprintf(LOG_ERR, "Error: invalid ISOL parameter %s", param);
  237. return -1;
  238. }
  239. /*
  240. * Execute the request
  241. */
  242. rsp = intf->sendrecv(intf, &req);
  243. if (rsp == NULL) {
  244. lprintf(LOG_ERR, "Error setting ISOL parameter '%s'", param);
  245. return -1;
  246. }
  247. if (rsp->ccode > 0) {
  248. lprintf(LOG_ERR, "Error setting ISOL parameter '%s': %s",
  249. param, val2str(rsp->ccode, completion_code_vals));
  250. return -1;
  251. }
  252. return 0;
  253. }
  254. static void
  255. leave_raw_mode(void)
  256. {
  257. if (!_in_raw_mode)
  258. return;
  259. if (tcsetattr(fileno(stdin), TCSADRAIN, &_saved_tio) == -1)
  260. perror("tcsetattr");
  261. else
  262. _in_raw_mode = 0;
  263. }
  264. static void
  265. enter_raw_mode(void)
  266. {
  267. struct termios tio;
  268. if (tcgetattr(fileno(stdin), &tio) == -1) {
  269. perror("tcgetattr");
  270. return;
  271. }
  272. _saved_tio = tio;
  273. tio.c_iflag |= IGNPAR;
  274. tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF)\
  275. ;
  276. tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
  277. // #ifdef IEXTEN
  278. tio.c_lflag &= ~IEXTEN;
  279. // #endif
  280. tio.c_oflag &= ~OPOST;
  281. tio.c_cc[VMIN] = 1;
  282. tio.c_cc[VTIME] = 0;
  283. if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) == -1)
  284. perror("tcsetattr");
  285. else
  286. _in_raw_mode = 1;
  287. }
  288. static void
  289. sendBreak(struct ipmi_intf * intf)
  290. {
  291. struct ipmi_v2_payload v2_payload;
  292. memset(&v2_payload, 0, sizeof(v2_payload));
  293. v2_payload.payload.sol_packet.character_count = 0;
  294. v2_payload.payload.sol_packet.generate_break = 1;
  295. intf->send_sol(intf, &v2_payload);
  296. }
  297. /*
  298. * suspendSelf
  299. *
  300. * Put ourself in the background
  301. *
  302. * param bRestoreTty specifies whether we will put our self back
  303. * in raw mode when we resume
  304. */
  305. static void
  306. suspendSelf(int bRestoreTty)
  307. {
  308. leave_raw_mode();
  309. kill(getpid(), SIGTSTP);
  310. if (bRestoreTty)
  311. enter_raw_mode();
  312. }
  313. /*
  314. * printiSolEscapeSequences
  315. *
  316. * Send some useful documentation to the user
  317. */
  318. static void
  319. printiSolEscapeSequences(void)
  320. {
  321. printf(
  322. "%c?\n\
  323. Supported escape sequences:\n\
  324. %c. - terminate connection\n\
  325. %c^Z - suspend ipmitool\n\
  326. %c^X - suspend ipmitool, but don't restore tty on restart\n\
  327. %cB - send break\n\
  328. %c? - this message\n\
  329. %c%c - send the escape character by typing it twice\n\
  330. (Note that escapes are only recognized immediately after newline.)\n",
  331. ISOL_ESCAPE_CHARACTER,
  332. ISOL_ESCAPE_CHARACTER,
  333. ISOL_ESCAPE_CHARACTER,
  334. ISOL_ESCAPE_CHARACTER,
  335. ISOL_ESCAPE_CHARACTER,
  336. ISOL_ESCAPE_CHARACTER,
  337. ISOL_ESCAPE_CHARACTER,
  338. ISOL_ESCAPE_CHARACTER);
  339. }
  340. /*
  341. * output
  342. *
  343. * Send the specified data to stdout
  344. */
  345. static void
  346. output(struct ipmi_rs * rsp)
  347. {
  348. if (rsp)
  349. {
  350. int i;
  351. for (i = 0; i < rsp->data_len; ++i)
  352. putc(rsp->data[i], stdout);
  353. fflush(stdout);
  354. }
  355. }
  356. /*
  357. * ipmi_isol_deactivate
  358. */
  359. static int
  360. ipmi_isol_deactivate(struct ipmi_intf * intf)
  361. {
  362. struct ipmi_rs * rsp;
  363. struct ipmi_rq req;
  364. uint8_t data[6];
  365. memset(&req, 0, sizeof(req));
  366. req.msg.netfn = IPMI_NETFN_ISOL;
  367. req.msg.cmd = ACTIVATE_ISOL;
  368. req.msg.data = data;
  369. req.msg.data_len = 5;
  370. memset(data, 0, 6);
  371. data[0] = 0x00; /* Deactivate */
  372. data[1] = 0x00;
  373. data[2] = 0x00;
  374. data[3] = 0x00;
  375. data[5] = 0x00;
  376. rsp = intf->sendrecv(intf, &req);
  377. if (rsp == NULL) {
  378. lprintf(LOG_ERR, "Error deactivating ISOL");
  379. return -1;
  380. }
  381. if (rsp->ccode > 0) {
  382. lprintf(LOG_ERR, "Error deactivating ISOL: %s",
  383. val2str(rsp->ccode, completion_code_vals));
  384. return -1;
  385. }
  386. /* response contain 4 additional bytes : 80 00 32 ff
  387. Don't know what to use them for yet... */
  388. return 0;
  389. }
  390. /*
  391. * processiSolUserInput
  392. *
  393. * Act on user input into the ISOL session. The only reason this
  394. * is complicated is that we have to process escape sequences.
  395. *
  396. * return 0 on success
  397. * 1 if we should exit
  398. * < 0 on error (BMC probably closed the session)
  399. */
  400. static int
  401. processiSolUserInput(struct ipmi_intf * intf,
  402. uint8_t * input,
  403. uint16_t buffer_length)
  404. {
  405. static int escape_pending = 0;
  406. static int last_was_cr = 1;
  407. struct ipmi_v2_payload v2_payload;
  408. int length = 0;
  409. int retval = 0;
  410. char ch;
  411. int i;
  412. memset(&v2_payload, 0, sizeof(v2_payload));
  413. /*
  414. * Our first order of business is to check the input for escape
  415. * sequences to act on.
  416. */
  417. for (i = 0; i < buffer_length; ++i)
  418. {
  419. ch = input[i];
  420. if (escape_pending){
  421. escape_pending = 0;
  422. /*
  423. * Process a possible escape sequence.
  424. */
  425. switch (ch) {
  426. case '.':
  427. printf("%c. [terminated ipmitool]\n", ISOL_ESCAPE_CHARACTER);
  428. retval = 1;
  429. break;
  430. case 'Z' - 64:
  431. printf("%c^Z [suspend ipmitool]\n", ISOL_ESCAPE_CHARACTER);
  432. suspendSelf(1); /* Restore tty back to raw */
  433. continue;
  434. case 'X' - 64:
  435. printf("%c^X [suspend ipmitool]\n", ISOL_ESCAPE_CHARACTER);
  436. suspendSelf(0); /* Don't restore to raw mode */
  437. continue;
  438. case 'B':
  439. printf("%cb [send break]\n", ISOL_ESCAPE_CHARACTER);
  440. sendBreak(intf);
  441. continue;
  442. case '?':
  443. printiSolEscapeSequences();
  444. continue;
  445. default:
  446. if (ch != ISOL_ESCAPE_CHARACTER)
  447. v2_payload.payload.sol_packet.data[length++] =
  448. ISOL_ESCAPE_CHARACTER;
  449. v2_payload.payload.sol_packet.data[length++] = ch;
  450. }
  451. }
  452. else
  453. {
  454. if (last_was_cr && (ch == ISOL_ESCAPE_CHARACTER)) {
  455. escape_pending = 1;
  456. continue;
  457. }
  458. v2_payload.payload.sol_packet.data[length++] = ch;
  459. }
  460. /*
  461. * Normal character. Record whether it was a newline.
  462. */
  463. last_was_cr = (ch == '\r' || ch == '\n');
  464. }
  465. /*
  466. * If there is anything left to process we dispatch it to the BMC,
  467. * send intf->session->sol_data.max_outbound_payload_size bytes
  468. * at a time.
  469. */
  470. if (length)
  471. {
  472. struct ipmi_rs * rsp;
  473. v2_payload.payload.sol_packet.flush_outbound = 1; /* Not sure if necessary ? */
  474. v2_payload.payload.sol_packet.character_count = length;
  475. rsp = intf->send_sol(intf, &v2_payload);
  476. if (! rsp) {
  477. lprintf(LOG_ERR, "Error sending SOL data");
  478. retval = -1;
  479. }
  480. /* If the sequence number is set we know we have new data */
  481. else if ((rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) &&
  482. (rsp->payload.sol_packet.packet_sequence_number))
  483. output(rsp);
  484. }
  485. return retval;
  486. }
  487. /*
  488. * ipmi_isol_red_pill
  489. */
  490. static int
  491. ipmi_isol_red_pill(struct ipmi_intf * intf)
  492. {
  493. char * buffer;
  494. int numRead;
  495. int bShouldExit = 0;
  496. int bBmcClosedSession = 0;
  497. fd_set read_fds;
  498. struct timeval tv;
  499. int retval;
  500. int buffer_size = 255;
  501. int timedout = 0;
  502. buffer = (char*)malloc(buffer_size);
  503. if (buffer == NULL) {
  504. lprintf(LOG_ERR, "ipmitool: malloc failure");
  505. return -1;
  506. }
  507. enter_raw_mode();
  508. while (! bShouldExit)
  509. {
  510. FD_ZERO(&read_fds);
  511. FD_SET(0, &read_fds);
  512. FD_SET(intf->fd, &read_fds);
  513. /* Wait up to half a second */
  514. tv.tv_sec = 0;
  515. tv.tv_usec = 500000;
  516. retval = select(intf->fd + 1, &read_fds, NULL, NULL, &tv);
  517. if (retval)
  518. {
  519. if (retval == -1)
  520. {
  521. /* ERROR */
  522. perror("select");
  523. return -1;
  524. }
  525. timedout = 0;
  526. /*
  527. * Process input from the user
  528. */
  529. if (FD_ISSET(0, &read_fds))
  530. {
  531. memset(buffer, 0, buffer_size);
  532. numRead = read(fileno(stdin),
  533. buffer,
  534. buffer_size);
  535. if (numRead > 0)
  536. {
  537. int rc = processiSolUserInput(intf, buffer, numRead);
  538. if (rc)
  539. {
  540. if (rc < 0)
  541. bShouldExit = bBmcClosedSession = 1;
  542. else
  543. bShouldExit = 1;
  544. }
  545. }
  546. else
  547. {
  548. bShouldExit = 1;
  549. }
  550. }
  551. /*
  552. * Process input from the BMC
  553. */
  554. else if (FD_ISSET(intf->fd, &read_fds))
  555. {
  556. struct ipmi_rs * rs = intf->recv_sol(intf);
  557. if (! rs)
  558. {
  559. bShouldExit = bBmcClosedSession = 1;
  560. }
  561. else
  562. output(rs);
  563. }
  564. /*
  565. * ERROR in select
  566. */
  567. else
  568. {
  569. lprintf(LOG_ERR, "Error: Select returned with nothing to read");
  570. bShouldExit = 1;
  571. }
  572. }
  573. else
  574. {
  575. if ((++timedout) == 20) /* Every 10 seconds we send a keepalive */
  576. {
  577. intf->keepalive(intf);
  578. timedout = 0;
  579. }
  580. }
  581. }
  582. leave_raw_mode();
  583. if (bBmcClosedSession)
  584. {
  585. lprintf(LOG_ERR, "SOL session closed by BMC");
  586. }
  587. else
  588. ipmi_isol_deactivate(intf);
  589. return 0;
  590. }
  591. /*
  592. * ipmi_isol_activate
  593. */
  594. static int
  595. ipmi_isol_activate(struct ipmi_intf * intf)
  596. {
  597. struct ipmi_rs * rsp;
  598. struct ipmi_rq req;
  599. uint8_t data[6];
  600. struct isol_config_parameters params;
  601. if (ipmi_get_isol_info(intf, &params))
  602. return -1;
  603. if (!(params.enabled & 0x1)) {
  604. lprintf(LOG_ERR, "ISOL is not enabled!");
  605. return -1;
  606. }
  607. /*
  608. * Setup a callback so that the lanplus processing knows what
  609. * to do with packets that come unexpectedly (while waiting for
  610. * an ACK, perhaps.
  611. */
  612. intf->session->sol_data.sol_input_handler = output;
  613. memset(&req, 0, sizeof(req));
  614. req.msg.netfn = IPMI_NETFN_ISOL;
  615. req.msg.cmd = ACTIVATE_ISOL;
  616. req.msg.data = data;
  617. req.msg.data_len = 5;
  618. memset(data, 0, 6);
  619. data[0] = 0x01;
  620. data[1] = 0x00;
  621. data[2] = 0x00;
  622. data[3] = 0x00;
  623. data[5] = 0x00;
  624. rsp = intf->sendrecv(intf, &req);
  625. if (NULL != rsp) {
  626. switch (rsp->ccode) {
  627. case 0x00:
  628. if (rsp->data_len == 4) {
  629. break;
  630. } else {
  631. lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
  632. "in ISOL activation response",
  633. rsp->data_len);
  634. return -1;
  635. }
  636. break;
  637. case 0x80:
  638. lprintf(LOG_ERR, "Info: ISOL already active on another session");
  639. return -1;
  640. case 0x81:
  641. lprintf(LOG_ERR, "Info: ISOL disabled");
  642. return -1;
  643. case 0x82:
  644. lprintf(LOG_ERR, "Info: ISOL activation limit reached");
  645. return -1;
  646. default:
  647. lprintf(LOG_ERR, "Error activating ISOL: %s",
  648. val2str(rsp->ccode, completion_code_vals));
  649. return -1;
  650. }
  651. } else {
  652. lprintf(LOG_ERR, "Error: No response activating ISOL");
  653. return -1;
  654. }
  655. /* response contain 4 additional bytes : 80 01 32 ff
  656. Don't know what to use them for yet... */
  657. printf("[SOL Session operational. Use %c? for help]\n",
  658. ISOL_ESCAPE_CHARACTER);
  659. /*
  660. * At this point we are good to go with our SOL session. We
  661. * need to listen to
  662. * 1) STDIN for user input
  663. * 2) The FD for incoming SOL packets
  664. */
  665. if (ipmi_isol_red_pill(intf)) {
  666. lprintf(LOG_ERR, "Error in SOL session");
  667. return -1;
  668. }
  669. return 0;
  670. }
  671. static void print_isol_set_usage(void) {
  672. lprintf(LOG_NOTICE, "\nISOL set parameters and values: \n");
  673. lprintf(LOG_NOTICE, " enabled true | false");
  674. lprintf(LOG_NOTICE, " privilege-level user | operator | admin | oem");
  675. lprintf(LOG_NOTICE, " bit-rate "
  676. "9.6 | 19.2 | 38.4 | 57.6 | 115.2");
  677. lprintf(LOG_NOTICE, "");
  678. }
  679. static void print_isol_usage(void) {
  680. lprintf(LOG_NOTICE, "ISOL Commands: info");
  681. lprintf(LOG_NOTICE, " set <parameter> <setting>");
  682. lprintf(LOG_NOTICE, " activate");
  683. }
  684. int ipmi_isol_main(struct ipmi_intf * intf, int argc, char ** argv)
  685. {
  686. int ret = 0;
  687. /*
  688. * Help
  689. */
  690. if (!argc || !strncmp(argv[0], "help", 4))
  691. print_isol_usage();
  692. /*
  693. * Info
  694. */
  695. else if (!strncmp(argv[0], "info", 4)) {
  696. ret = ipmi_print_isol_info(intf);
  697. }
  698. /*
  699. * Set a parameter value
  700. */
  701. else if (!strncmp(argv[0], "set", 3)) {
  702. if (argc < 3) {
  703. print_isol_set_usage();
  704. return -1;
  705. }
  706. ret = ipmi_isol_set_param(intf, argv[1], argv[2]);
  707. }
  708. /*
  709. * Activate
  710. */
  711. else if (!strncmp(argv[0], "activate", 8)) {
  712. ret = ipmi_isol_activate(intf);
  713. }
  714. else {
  715. print_isol_usage();
  716. ret = -1;
  717. }
  718. return ret;
  719. }