ipmi_firewall.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194
  1. /*
  2. * Copyright (c) 2005 International Business Machines, Inc. All Rights Reserved.
  3. * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * Redistribution of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * Redistribution in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * Neither the name of Sun Microsystems, Inc. or the names of
  17. * contributors may be used to endorse or promote products derived
  18. * from this software without specific prior written permission.
  19. *
  20. * This software is provided "AS IS," without a warranty of any kind.
  21. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
  22. * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
  23. * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
  24. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
  25. * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
  26. * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
  27. * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
  28. * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
  29. * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
  30. * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
  31. * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  32. */
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <stdio.h>
  36. #include <time.h>
  37. #include <ipmitool/helper.h>
  38. #include <ipmitool/log.h>
  39. #include <ipmitool/bswap.h>
  40. #include <ipmitool/ipmi.h>
  41. #include <ipmitool/ipmi_intf.h>
  42. #include <ipmitool/ipmi_firewall.h>
  43. #include <ipmitool/ipmi_strings.h>
  44. static void
  45. printf_firewall_usage(void)
  46. {
  47. lprintf(LOG_NOTICE,
  48. "Firmware Firewall Commands:");
  49. lprintf(LOG_NOTICE,
  50. "\tinfo [channel H] [lun L]");
  51. lprintf(LOG_NOTICE,
  52. "\tinfo [channel H] [lun L [netfn N [command C [subfn S]]]]");
  53. lprintf(LOG_NOTICE,
  54. "\tenable [channel H] [lun L [netfn N [command C [subfn S]]]]");
  55. lprintf(LOG_NOTICE,
  56. "\tdisable [channel H] [lun L [netfn N [command C [subfn S]]]] [force])");
  57. lprintf(LOG_NOTICE,
  58. "\treset [channel H]");
  59. lprintf(LOG_NOTICE,
  60. "\t\twhere H is a Channel, L is a LUN, N is a NetFn,");
  61. lprintf(LOG_NOTICE,
  62. "\t\tC is a Command and S is a Sub-Function");
  63. }
  64. void
  65. printf_firewall_info_usage(void)
  66. {
  67. lprintf(LOG_NOTICE,
  68. "info [channel H]");
  69. lprintf(LOG_NOTICE,
  70. "\tList all of the firewall information for all LUNs, NetFns");
  71. lprintf(LOG_NOTICE,
  72. "\tand Commands, This is a long list and is not very human readable.");
  73. lprintf(LOG_NOTICE,
  74. "info [channel H] lun L");
  75. lprintf(LOG_NOTICE,
  76. "\tThis also prints a long list that is not very human readable.");
  77. lprintf(LOG_NOTICE,
  78. "info [channel H] lun L netfn N");
  79. lprintf(LOG_NOTICE,
  80. "\tThis prints out information for a single LUN/NetFn pair.");
  81. lprintf(LOG_NOTICE,
  82. "\tThat is not really very usable, but at least it is short.");
  83. lprintf(LOG_NOTICE,
  84. "info [channel H] lun L netfn N command C");
  85. lprintf(LOG_NOTICE,
  86. "\tThis is the one you want -- it prints out detailed human");
  87. lprintf(LOG_NOTICE,
  88. "\treadable information. It shows the support, configurable, and");
  89. lprintf(LOG_NOTICE,
  90. "\tenabled bits for the Command C on LUN/NetFn pair L,N and the");
  91. lprintf(LOG_NOTICE,
  92. "\tsame information about each of its Sub-functions.");
  93. }
  94. // print n bytes of bit field bf (if invert, print ~bf)
  95. static void print_bitfield(const unsigned char * bf, int n, int invert, int loglevel) {
  96. int i = 0;
  97. if (loglevel < 0) {
  98. while (i<n) {
  99. printf("%02x", (unsigned char) (invert?~bf[i]:bf[i]));
  100. if (++i % 4 == 0)
  101. printf(" ");
  102. }
  103. printf("\n");
  104. } else {
  105. while (i<n) {
  106. lprintf(loglevel, "%02x", (unsigned char) (invert?~bf[i]:bf[i]));
  107. if (++i % 4 == 0)
  108. lprintf(loglevel, " ");
  109. }
  110. lprintf(loglevel, "\n");
  111. }
  112. }
  113. static int
  114. ipmi_firewall_parse_args(int argc, char ** argv, struct ipmi_function_params * p)
  115. {
  116. int i;
  117. uint8_t conv_err = 0;
  118. if (!p) {
  119. lprintf(LOG_ERR, "ipmi_firewall_parse_args: p is NULL");
  120. return -1;
  121. }
  122. for (i=0; i<argc; i++) {
  123. if (strncmp(argv[i], "channel", 7) == 0 && (++i < argc)) {
  124. uint8_t channel_tmp = 0;
  125. if (is_ipmi_channel_num(argv[i], &channel_tmp) != 0) {
  126. conv_err = 1;
  127. break;
  128. } else {
  129. p->channel = channel_tmp;
  130. }
  131. }
  132. else if (strncmp(argv[i], "lun", 3) == 0 && (++i < argc)) {
  133. if (str2int(argv[i], &(p->lun)) != 0) {
  134. lprintf(LOG_ERR, "Given lun '%s' is invalid.", argv[i]);
  135. conv_err = 1;
  136. break;
  137. }
  138. }
  139. else if (strncmp(argv[i], "force", 5) == 0) {
  140. p->force = 1;
  141. }
  142. else if (strncmp(argv[i], "netfn", 5) == 0 && (++i < argc)) {
  143. if (str2int(argv[i], &(p->netfn)) != 0) {
  144. lprintf(LOG_ERR, "Given netfn '%s' is invalid.", argv[i]);
  145. conv_err = 1;
  146. break;
  147. }
  148. }
  149. else if (strncmp(argv[i], "command", 7) == 0 && (++i < argc)) {
  150. if (str2int(argv[i], &(p->command)) != 0) {
  151. lprintf(LOG_ERR, "Given command '%s' is invalid.", argv[i]);
  152. conv_err = 1;
  153. break;
  154. }
  155. }
  156. else if (strncmp(argv[i], "subfn", 5) == 0 && (++i < argc)) {
  157. if (str2int(argv[i], &(p->subfn)) != 0) {
  158. lprintf(LOG_ERR, "Given subfn '%s' is invalid.", argv[i]);
  159. conv_err = 1;
  160. break;
  161. }
  162. }
  163. }
  164. if (conv_err != 0) {
  165. return (-1);
  166. }
  167. if (p->subfn >= MAX_SUBFN) {
  168. lprintf(LOG_ERR, "subfn is out of range (0-%d)", MAX_SUBFN-1);
  169. return -1;
  170. }
  171. if (p->command >= MAX_COMMAND) {
  172. lprintf(LOG_ERR, "command is out of range (0-%d)", MAX_COMMAND-1);
  173. return -1;
  174. }
  175. if (p->netfn >= MAX_NETFN) {
  176. lprintf(LOG_ERR, "netfn is out of range (0-%d)", MAX_NETFN-1);
  177. return -1;
  178. }
  179. if (p->lun >= MAX_LUN) {
  180. lprintf(LOG_ERR, "lun is out of range (0-%d)", MAX_LUN-1);
  181. return -1;
  182. }
  183. if (p->netfn >= 0 && p->lun < 0) {
  184. lprintf(LOG_ERR, "if netfn is set, so must be lun");
  185. return -1;
  186. }
  187. if (p->command >= 0 && p->netfn < 0) {
  188. lprintf(LOG_ERR, "if command is set, so must be netfn");
  189. return -1;
  190. }
  191. if (p->subfn >= 0 && p->command < 0) {
  192. lprintf(LOG_ERR, "if subfn is set, so must be command");
  193. return -1;
  194. }
  195. return 0;
  196. }
  197. /* _get_netfn_suport
  198. *
  199. * @intf: ipmi interface
  200. * @channel: ipmi channel
  201. * @lun: a pointer to a 4 byte field
  202. * @netfn: a pointer to a 128-bit bitfield (16 bytes)
  203. *
  204. * returns 0 on success and fills in the bitfield for
  205. * the 32 netfn * 4 LUN pairs that support commands
  206. * returns -1 on error
  207. */
  208. static int
  209. _get_netfn_support(struct ipmi_intf * intf, int channel, unsigned char * lun, unsigned char * netfn)
  210. {
  211. struct ipmi_rs * rsp;
  212. struct ipmi_rq req;
  213. unsigned char * d, rqdata;
  214. unsigned int l;
  215. if (!lun || !netfn) {
  216. lprintf(LOG_ERR, "_get_netfn_suport: lun or netfn is NULL");
  217. return -1;
  218. }
  219. memset(&req, 0, sizeof(req));
  220. req.msg.netfn = IPMI_NETFN_APP;
  221. req.msg.cmd = BMC_GET_NETFN_SUPPORT;
  222. rqdata = (unsigned char) channel;
  223. req.msg.data = &rqdata;
  224. req.msg.data_len = 1;
  225. rsp = intf->sendrecv(intf, &req);
  226. if (rsp == NULL) {
  227. lprintf(LOG_ERR, "Get NetFn Support command failed");
  228. return -1;
  229. }
  230. if (rsp->ccode > 0) {
  231. lprintf(LOG_ERR, "Get NetFn Support command failed: %s",
  232. val2str(rsp->ccode, completion_code_vals));
  233. return -1;
  234. }
  235. d = rsp->data;
  236. for (l=0; l<4; l++) {
  237. lun[l] = (*d)>>(2*l) & 0x3;
  238. }
  239. d++;
  240. memcpy(netfn, d, 16);
  241. return 0;
  242. }
  243. /* _get_command_suport
  244. *
  245. * @intf: ipmi interface
  246. * @p: a pointer to a struct ipmi_function_params
  247. * @lnfn: a pointer to a struct lun_netfn_support
  248. *
  249. * returns 0 on success and fills in lnfn according to the request in p
  250. * returns -1 on error
  251. */
  252. static int
  253. _get_command_support(struct ipmi_intf * intf,
  254. struct ipmi_function_params * p, struct lun_netfn_support * lnfn)
  255. {
  256. struct ipmi_rs * rsp;
  257. struct ipmi_rq req;
  258. unsigned char * d, rqdata[3];
  259. unsigned int c;
  260. if (!p || !lnfn) {
  261. lprintf(LOG_ERR, "_get_netfn_suport: p or lnfn is NULL");
  262. return -1;
  263. }
  264. memset(&req, 0, sizeof(req));
  265. req.msg.netfn = IPMI_NETFN_APP;
  266. req.msg.cmd = BMC_GET_COMMAND_SUPPORT;
  267. rqdata[0] = (unsigned char) p->channel;
  268. rqdata[1] = p->netfn;
  269. rqdata[2] = p->lun;
  270. req.msg.data = rqdata;
  271. req.msg.data_len = 3;
  272. rsp = intf->sendrecv(intf, &req);
  273. if (rsp == NULL) {
  274. lprintf(LOG_ERR, "Get Command Support (LUN=%d, NetFn=%d, op=0) command failed", p->lun, p->netfn);
  275. return -1;
  276. }
  277. if (rsp->ccode > 0) {
  278. lprintf(LOG_ERR, "Get Command Support (LUN=%d, NetFn=%d, op=0) command failed: %s",
  279. p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
  280. return -1;
  281. }
  282. d = rsp->data;
  283. for (c=0; c<128; c++) {
  284. if (!(d[c>>3] & (1<<(c%8))))
  285. lnfn->command[c].support |= BIT_AVAILABLE;
  286. }
  287. memcpy(lnfn->command_mask, d, MAX_COMMAND_BYTES/2);
  288. memset(&req, 0, sizeof(req));
  289. req.msg.netfn = IPMI_NETFN_APP;
  290. req.msg.cmd = BMC_GET_COMMAND_SUPPORT;
  291. rqdata[0] = (unsigned char) p->channel;
  292. rqdata[1] = 0x40 | p->netfn;
  293. rqdata[2] = p->lun;
  294. req.msg.data = rqdata;
  295. req.msg.data_len = 3;
  296. rsp = intf->sendrecv(intf, &req);
  297. if (rsp == NULL) {
  298. lprintf(LOG_ERR, "Get Command Support (LUN=%d, NetFn=%d, op=1) command failed", p->lun, p->netfn);
  299. return -1;
  300. }
  301. if (rsp->ccode > 0) {
  302. lprintf(LOG_ERR, "Get Command Support (LUN=%d, NetFn=%d, op=1) command failed: %s",
  303. p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
  304. return -1;
  305. }
  306. d = rsp->data;
  307. for (c=0; c<128; c++) {
  308. if (!(d[c>>3] & (1<<(c%8))))
  309. lnfn->command[128+c].support |= BIT_AVAILABLE;
  310. }
  311. memcpy(lnfn->command_mask+MAX_COMMAND_BYTES/2, d, MAX_COMMAND_BYTES/2);
  312. return 0;
  313. }
  314. /* _get_command_configurable
  315. *
  316. * @intf: ipmi interface
  317. * @p: a pointer to a struct ipmi_function_params
  318. * @lnfn: a pointer to a struct lun_netfn_support
  319. *
  320. * returns 0 on success and fills in lnfn according to the request in p
  321. * returns -1 on error
  322. */
  323. static int
  324. _get_command_configurable(struct ipmi_intf * intf,
  325. struct ipmi_function_params * p, struct lun_netfn_support * lnfn)
  326. {
  327. struct ipmi_rs * rsp;
  328. struct ipmi_rq req;
  329. unsigned char * d, rqdata[3];
  330. unsigned int c;
  331. if (!p || !lnfn) {
  332. lprintf(LOG_ERR, "_get_command_configurable: p or lnfn is NULL");
  333. return -1;
  334. }
  335. memset(&req, 0, sizeof(req));
  336. req.msg.netfn = IPMI_NETFN_APP;
  337. req.msg.cmd = BMC_GET_CONFIGURABLE_COMMANDS;
  338. rqdata[0] = (unsigned char) p->channel;
  339. rqdata[1] = p->netfn;
  340. rqdata[2] = p->lun;
  341. req.msg.data = rqdata;
  342. req.msg.data_len = 3;
  343. rsp = intf->sendrecv(intf, &req);
  344. if (rsp == NULL) {
  345. lprintf(LOG_ERR, "Get Configurable Command (LUN=%d, NetFn=%d, op=0) command failed", p->lun, p->netfn);
  346. return -1;
  347. }
  348. if (rsp->ccode > 0) {
  349. lprintf(LOG_ERR, "Get Configurable Command (LUN=%d, NetFn=%d, op=0) command failed: %s",
  350. p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
  351. return -1;
  352. }
  353. d = rsp->data;
  354. for (c=0; c<128; c++) {
  355. if (d[c>>3] & (1<<(c%8)))
  356. lnfn->command[c].support |= BIT_CONFIGURABLE;
  357. }
  358. memcpy(lnfn->config_mask, d, MAX_COMMAND_BYTES/2);
  359. memset(&req, 0, sizeof(req));
  360. req.msg.netfn = IPMI_NETFN_APP;
  361. req.msg.cmd = BMC_GET_CONFIGURABLE_COMMANDS;
  362. rqdata[0] = (unsigned char) p->channel;
  363. rqdata[1] = 0x40 | p->netfn;
  364. rqdata[2] = p->lun;
  365. req.msg.data = rqdata;
  366. req.msg.data_len = 3;
  367. rsp = intf->sendrecv(intf, &req);
  368. if (rsp == NULL) {
  369. lprintf(LOG_ERR, "Get Configurable Command (LUN=%d, NetFn=%d, op=1) command failed", p->lun, p->netfn);
  370. return -1;
  371. }
  372. if (rsp->ccode > 0) {
  373. lprintf(LOG_ERR, "Get Configurable Command (LUN=%d, NetFn=%d, op=1) command failed: %s",
  374. p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
  375. return -1;
  376. }
  377. d = rsp->data;
  378. for (c=0; c<128; c++) {
  379. if (d[c>>3] & (1<<(c%8)))
  380. lnfn->command[128+c].support |= BIT_CONFIGURABLE;
  381. }
  382. memcpy(lnfn->config_mask+MAX_COMMAND_BYTES/2, d, MAX_COMMAND_BYTES/2);
  383. return 0;
  384. }
  385. /* _get_command_enables
  386. *
  387. * @intf: ipmi interface
  388. * @p: a pointer to a struct ipmi_function_params
  389. * @lnfn: a pointer to a struct lun_netfn_support
  390. *
  391. * returns 0 on success and fills in lnfn according to the request in p
  392. * returns -1 on error
  393. */
  394. static int
  395. _get_command_enables(struct ipmi_intf * intf,
  396. struct ipmi_function_params * p, struct lun_netfn_support * lnfn)
  397. {
  398. struct ipmi_rs * rsp;
  399. struct ipmi_rq req;
  400. unsigned char * d, rqdata[3];
  401. unsigned int c;
  402. if (!p || !lnfn) {
  403. lprintf(LOG_ERR, "_get_command_enables: p or lnfn is NULL");
  404. return -1;
  405. }
  406. memset(&req, 0, sizeof(req));
  407. req.msg.netfn = IPMI_NETFN_APP;
  408. req.msg.cmd = BMC_GET_COMMAND_ENABLES;
  409. rqdata[0] = (unsigned char) p->channel;
  410. rqdata[1] = p->netfn;
  411. rqdata[2] = p->lun;
  412. req.msg.data = rqdata;
  413. req.msg.data_len = 3;
  414. rsp = intf->sendrecv(intf, &req);
  415. if (rsp == NULL) {
  416. lprintf(LOG_ERR, "Get Command Enables (LUN=%d, NetFn=%d, op=0) command failed", p->lun, p->netfn);
  417. return -1;
  418. }
  419. if (rsp->ccode > 0) {
  420. lprintf(LOG_ERR, "Get Command Enables (LUN=%d, NetFn=%d, op=0) command failed: %s",
  421. p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
  422. return -1;
  423. }
  424. d = rsp->data;
  425. for (c=0; c<128; c++) {
  426. if (d[c>>3] & (1<<(c%8)))
  427. lnfn->command[c].support |= BIT_ENABLED;
  428. }
  429. memcpy(lnfn->enable_mask, d, MAX_COMMAND_BYTES/2);
  430. memset(&req, 0, sizeof(req));
  431. req.msg.netfn = IPMI_NETFN_APP;
  432. req.msg.cmd = BMC_GET_COMMAND_ENABLES;
  433. rqdata[0] = (unsigned char) p->channel;
  434. rqdata[1] = 0x40 | p->netfn;
  435. rqdata[2] = p->lun;
  436. req.msg.data = rqdata;
  437. req.msg.data_len = 3;
  438. rsp = intf->sendrecv(intf, &req);
  439. if (rsp == NULL) {
  440. lprintf(LOG_ERR, "Get Command Enables (LUN=%d, NetFn=%d, op=1) command failed", p->lun, p->netfn);
  441. return -1;
  442. }
  443. if (rsp->ccode > 0) {
  444. lprintf(LOG_ERR, "Get Command Enables (LUN=%d, NetFn=%d, op=1) command failed: %s",
  445. p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
  446. return -1;
  447. }
  448. d = rsp->data;
  449. for (c=0; c<128; c++) {
  450. if (d[c>>3] & (1<<(c%8)))
  451. lnfn->command[128+c].support |= BIT_ENABLED;
  452. }
  453. memcpy(lnfn->enable_mask+MAX_COMMAND_BYTES/2, d, MAX_COMMAND_BYTES/2);
  454. return 0;
  455. }
  456. /* _set_command_enables
  457. *
  458. * @intf: ipmi interface
  459. * @p: a pointer to a struct ipmi_function_params
  460. * @lnfn: a pointer to a struct lun_netfn_support that contains current info
  461. * @enable: a pointer to a 32 byte bitfield that contains the desired enable state
  462. * @gun: here is a gun to shoot yourself in the foot. If this is true
  463. * you are allowed to disable this command
  464. *
  465. * returns 0 on success
  466. * returns -1 on error
  467. */
  468. static int
  469. _set_command_enables(struct ipmi_intf * intf,
  470. struct ipmi_function_params * p, struct lun_netfn_support * lnfn,
  471. unsigned char * enable, int gun)
  472. {
  473. struct ipmi_rs * rsp;
  474. struct ipmi_rq req;
  475. unsigned char rqdata[19];
  476. unsigned int c;
  477. if (!p || !lnfn) {
  478. lprintf(LOG_ERR, "_set_command_enables: p or lnfn is NULL");
  479. return -1;
  480. }
  481. lprintf(LOG_INFO, "support: ");
  482. print_bitfield(lnfn->command_mask, MAX_COMMAND_BYTES, 1, LOG_INFO);
  483. lprintf(LOG_INFO, "configurable: ");
  484. print_bitfield(lnfn->config_mask, MAX_COMMAND_BYTES, 0, LOG_INFO);
  485. lprintf(LOG_INFO, "enabled: ");
  486. print_bitfield(lnfn->enable_mask, MAX_COMMAND_BYTES, 0, LOG_INFO);
  487. lprintf(LOG_INFO, "enable mask before: ");
  488. print_bitfield(enable, MAX_COMMAND_BYTES, 0, LOG_INFO);
  489. // mask off the appropriate bits (if not configurable, set enable bit
  490. // must be the same as the current enable bit)
  491. for (c=0; c<(MAX_COMMAND_BYTES); c++) {
  492. enable[c] = (lnfn->config_mask[c] & enable[c]) |
  493. (~lnfn->config_mask[c] & lnfn->enable_mask[c]);
  494. }
  495. // take the gun out of their hand if they are not supposed to have it
  496. if (!gun) {
  497. enable[SET_COMMAND_ENABLE_BYTE] =
  498. (lnfn->config_mask[SET_COMMAND_ENABLE_BYTE]
  499. & SET_COMMAND_ENABLE_BIT) |
  500. (~lnfn->config_mask[SET_COMMAND_ENABLE_BYTE]
  501. & lnfn->enable_mask[SET_COMMAND_ENABLE_BYTE]);
  502. }
  503. lprintf(LOG_INFO, "enable mask after: ");
  504. print_bitfield(enable, MAX_COMMAND_BYTES, 0, LOG_INFO);
  505. memset(&req, 0, sizeof(req));
  506. req.msg.netfn = IPMI_NETFN_APP;
  507. req.msg.cmd = BMC_SET_COMMAND_ENABLES;
  508. rqdata[0] = (unsigned char) p->channel;
  509. rqdata[1] = p->netfn;
  510. rqdata[2] = p->lun;
  511. memcpy(&rqdata[3], enable, MAX_COMMAND_BYTES/2);
  512. req.msg.data = rqdata;
  513. req.msg.data_len = 19;
  514. rsp = intf->sendrecv(intf, &req);
  515. if (rsp == NULL) {
  516. lprintf(LOG_ERR, "Set Command Enables (LUN=%d, NetFn=%d, op=0) command failed", p->lun, p->netfn);
  517. return -1;
  518. }
  519. if (rsp->ccode > 0) {
  520. lprintf(LOG_ERR, "Set Command Enables (LUN=%d, NetFn=%d, op=0) command failed: %s",
  521. p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
  522. return -1;
  523. }
  524. memset(&req, 0, sizeof(req));
  525. req.msg.netfn = IPMI_NETFN_APP;
  526. req.msg.cmd = BMC_SET_COMMAND_ENABLES;
  527. rqdata[0] = (unsigned char) p->channel;
  528. rqdata[1] = 0x40 | p->netfn;
  529. rqdata[2] = p->lun;
  530. memcpy(&rqdata[3], enable+MAX_COMMAND_BYTES/2, MAX_COMMAND_BYTES/2);
  531. req.msg.data = rqdata;
  532. req.msg.data_len = 19;
  533. rsp = intf->sendrecv(intf, &req);
  534. if (rsp == NULL) {
  535. lprintf(LOG_ERR, "Set Command Enables (LUN=%d, NetFn=%d, op=1) command failed", p->lun, p->netfn);
  536. return -1;
  537. }
  538. if (rsp->ccode > 0) {
  539. lprintf(LOG_ERR, "Set Command Enables (LUN=%d, NetFn=%d, op=1) command failed: %s",
  540. p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
  541. return -1;
  542. }
  543. return 0;
  544. }
  545. /* _get_subfn_support
  546. *
  547. * @intf: ipmi interface
  548. * @p: a pointer to a struct ipmi_function_params
  549. * @cmd: a pointer to a struct command_support
  550. *
  551. * returns 0 on success and fills in cmd according to the request in p
  552. * returns -1 on error
  553. */
  554. static int
  555. _get_subfn_support(struct ipmi_intf * intf,
  556. struct ipmi_function_params * p, struct command_support * cmd)
  557. {
  558. struct ipmi_rs * rsp;
  559. struct ipmi_rq req;
  560. unsigned char rqdata[4];
  561. if (!p || !cmd) {
  562. lprintf(LOG_ERR, "_get_subfn_support: p or cmd is NULL");
  563. return -1;
  564. }
  565. memset(&req, 0, sizeof(req));
  566. req.msg.netfn = IPMI_NETFN_APP;
  567. req.msg.cmd = BMC_GET_COMMAND_SUBFUNCTION_SUPPORT;
  568. rqdata[0] = (unsigned char) p->channel;
  569. rqdata[1] = p->netfn;
  570. rqdata[2] = p->lun;
  571. rqdata[3] = p->command;
  572. req.msg.data = rqdata;
  573. req.msg.data_len = 4;
  574. rsp = intf->sendrecv(intf, &req);
  575. if (rsp == NULL) {
  576. lprintf(LOG_ERR, "Get Command Sub-function Support (LUN=%d, NetFn=%d, command=%d) command failed", p->lun, p->netfn, p->command);
  577. return -1;
  578. }
  579. if (rsp->ccode > 0) {
  580. lprintf(LOG_ERR, "Get Command Sub-function Support (LUN=%d, NetFn=%d, command=%d) command failed: %s",
  581. p->lun, p->netfn, p->command, val2str(rsp->ccode, completion_code_vals));
  582. return -1;
  583. }
  584. memcpy(cmd->subfn_support, rsp->data, sizeof(cmd->subfn_support));
  585. return 0;
  586. }
  587. /* _get_subfn_configurable
  588. *
  589. * @intf: ipmi interface
  590. * @p: a pointer to a struct ipmi_function_params
  591. * @cmd: a pointer to a struct command_support
  592. *
  593. * returns 0 on success and fills in cmd according to the request in p
  594. * returns -1 on error
  595. */
  596. static int
  597. _get_subfn_configurable(struct ipmi_intf * intf,
  598. struct ipmi_function_params * p, struct command_support * cmd)
  599. {
  600. struct ipmi_rs * rsp;
  601. struct ipmi_rq req;
  602. unsigned char rqdata[4];
  603. if (!p || !cmd) {
  604. lprintf(LOG_ERR, "_get_subfn_configurable: p or cmd is NULL");
  605. return -1;
  606. }
  607. memset(&req, 0, sizeof(req));
  608. req.msg.netfn = IPMI_NETFN_APP;
  609. req.msg.cmd = BMC_GET_CONFIGURABLE_COMMAND_SUBFUNCTIONS;
  610. rqdata[0] = (unsigned char) p->channel;
  611. rqdata[1] = p->netfn;
  612. rqdata[2] = p->lun;
  613. rqdata[3] = p->command;
  614. req.msg.data = rqdata;
  615. req.msg.data_len = 4;
  616. rsp = intf->sendrecv(intf, &req);
  617. if (rsp == NULL) {
  618. lprintf(LOG_ERR, "Get Configurable Command Sub-function (LUN=%d, NetFn=%d, command=%d) command failed", p->lun, p->netfn, p->command);
  619. return -1;
  620. }
  621. if (rsp->ccode > 0) {
  622. lprintf(LOG_ERR, "Get Configurable Command Sub-function (LUN=%d, NetFn=%d, command=%d) command failed: %s",
  623. p->lun, p->netfn, p->command, val2str(rsp->ccode, completion_code_vals));
  624. return -1;
  625. }
  626. memcpy(cmd->subfn_config, rsp->data, sizeof(cmd->subfn_config));
  627. return 0;
  628. }
  629. /* _get_subfn_enables
  630. *
  631. * @intf: ipmi interface
  632. * @p: a pointer to a struct ipmi_function_params
  633. * @cmd: a pointer to a struct command_support
  634. *
  635. * returns 0 on success and fills in cmd according to the request in p
  636. * returns -1 on error
  637. */
  638. static int
  639. _get_subfn_enables(struct ipmi_intf * intf,
  640. struct ipmi_function_params * p, struct command_support * cmd)
  641. {
  642. struct ipmi_rs * rsp;
  643. struct ipmi_rq req;
  644. unsigned char rqdata[4];
  645. if (!p || !cmd) {
  646. lprintf(LOG_ERR, "_get_subfn_enables: p or cmd is NULL");
  647. return -1;
  648. }
  649. memset(&req, 0, sizeof(req));
  650. req.msg.netfn = IPMI_NETFN_APP;
  651. req.msg.cmd = BMC_GET_COMMAND_SUBFUNCTION_ENABLES;
  652. rqdata[0] = (unsigned char) p->channel;
  653. rqdata[1] = p->netfn;
  654. rqdata[2] = p->lun;
  655. rqdata[3] = p->command;
  656. req.msg.data = rqdata;
  657. req.msg.data_len = 4;
  658. rsp = intf->sendrecv(intf, &req);
  659. if (rsp == NULL) {
  660. lprintf(LOG_ERR, "Get Command Sub-function Enables (LUN=%d, NetFn=%d, command=%d) command failed", p->lun, p->netfn, p->command);
  661. return -1;
  662. }
  663. if (rsp->ccode > 0) {
  664. lprintf(LOG_ERR, "Get Command Sub-function Enables (LUN=%d, NetFn=%d, command=%d) command failed: %s",
  665. p->lun, p->netfn, p->command, val2str(rsp->ccode, completion_code_vals));
  666. return -1;
  667. }
  668. memcpy(cmd->subfn_enable, rsp->data, sizeof(cmd->subfn_enable));
  669. return 0;
  670. }
  671. /* _set_subfn_enables
  672. *
  673. * @intf: ipmi interface
  674. * @p: a pointer to a struct ipmi_function_params
  675. * @cmd: a pointer to a struct command_support
  676. * @enable: a pointer to a 4 byte bitfield that contains the desired enable state
  677. *
  678. * returns 0 on success (and modifies enable to be the bits it actually set)
  679. * returns -1 on error
  680. */
  681. static int
  682. _set_subfn_enables(struct ipmi_intf * intf,
  683. struct ipmi_function_params * p, struct command_support * cmd,
  684. unsigned char * enable)
  685. {
  686. struct ipmi_rs * rsp;
  687. struct ipmi_rq req;
  688. unsigned char rqdata[8];
  689. unsigned int c;
  690. if (!p || !cmd) {
  691. lprintf(LOG_ERR, "_set_subfn_enables: p or cmd is NULL");
  692. return -1;
  693. }
  694. lprintf(LOG_INFO, "support: ");
  695. print_bitfield(cmd->subfn_support, MAX_SUBFN_BYTES, 1, LOG_INFO);
  696. lprintf(LOG_INFO, "configurable: ");
  697. print_bitfield(cmd->subfn_config, MAX_SUBFN_BYTES, 0, LOG_INFO);
  698. lprintf(LOG_INFO, "enabled: ");
  699. print_bitfield(cmd->subfn_enable, MAX_SUBFN_BYTES, 0, LOG_INFO);
  700. lprintf(LOG_INFO, "enable mask before: ");
  701. print_bitfield(enable, MAX_SUBFN_BYTES, 0, LOG_INFO);
  702. // mask off the appropriate bits (if not configurable, set enable bit
  703. // must be the same as the current enable bit)
  704. for (c=0; c<sizeof(cmd->subfn_enable); c++) {
  705. enable[c] = (cmd->subfn_config[c] & enable[c]) |
  706. (~cmd->subfn_config[c] & cmd->subfn_enable[c]);
  707. }
  708. lprintf(LOG_INFO, "enable mask after: ");
  709. print_bitfield(enable, MAX_SUBFN_BYTES, 0, LOG_INFO);
  710. memset(&req, 0, sizeof(req));
  711. req.msg.netfn = IPMI_NETFN_APP;
  712. req.msg.cmd = BMC_SET_COMMAND_SUBFUNCTION_ENABLES;
  713. rqdata[0] = (unsigned char) p->channel;
  714. rqdata[1] = p->netfn;
  715. rqdata[2] = p->lun;
  716. rqdata[3] = p->command;
  717. memcpy(&rqdata[4], enable, MAX_SUBFN_BYTES);
  718. req.msg.data = rqdata;
  719. req.msg.data_len = 8;
  720. rsp = intf->sendrecv(intf, &req);
  721. if (rsp == NULL) {
  722. lprintf(LOG_ERR, "Set Command Sub-function Enables (LUN=%d, NetFn=%d, command=%d) command failed", p->lun, p->netfn, p->command);
  723. return -1;
  724. }
  725. if (rsp->ccode > 0) {
  726. lprintf(LOG_ERR, "Set Command Sub-function Enables (LUN=%d, NetFn=%d, command=%d) command failed: %s",
  727. p->lun, p->netfn, p->command, val2str(rsp->ccode, completion_code_vals));
  728. return -1;
  729. }
  730. return 0;
  731. }
  732. /* _gather_info
  733. *
  734. * @intf: ipmi interface
  735. * @p: a pointer to a struct ipmi_function_params
  736. * @bmc: a pointer to a struct bmc_fn_support
  737. * @enable: a pointer to a 4 byte bitfield that contains the desired enable state
  738. *
  739. * returns 0 on success and fills in bmc according to request p
  740. * returns -1 on error
  741. */
  742. static int _gather_info(struct ipmi_intf * intf, struct ipmi_function_params * p, struct bmc_fn_support * bmc)
  743. {
  744. int ret, l, n;
  745. unsigned char lun[MAX_LUN], netfn[16];
  746. ret = _get_netfn_support(intf, p->channel, lun, netfn);
  747. if (!ret) {
  748. for (l=0; l<MAX_LUN; l++) {
  749. if (p->lun >= 0 && p->lun != l)
  750. continue;
  751. bmc->lun[l].support = lun[l];
  752. if (lun[l]) {
  753. for (n=0; n<MAX_NETFN_PAIR; n++) {
  754. int offset = l*MAX_NETFN_PAIR+n;
  755. bmc->lun[l].netfn[n].support =
  756. !!(netfn[offset>>3] & (1<<(offset%8)));
  757. }
  758. }
  759. }
  760. }
  761. if (p->netfn >= 0) {
  762. if (!((p->lun < 0 || bmc->lun[p->lun].support) &&
  763. (p->netfn < 0 || bmc->lun[p->lun].netfn[p->netfn>>1].support))) {
  764. lprintf(LOG_ERR, "LUN or LUN/NetFn pair %d,%d not supported", p->lun, p->netfn);
  765. return 0;
  766. }
  767. ret = _get_command_support(intf, p, &(bmc->lun[p->lun].netfn[p->netfn>>1]));
  768. ret |= _get_command_configurable(intf, p, &(bmc->lun[p->lun].netfn[p->netfn>>1]));
  769. ret |= _get_command_enables(intf, p, &(bmc->lun[p->lun].netfn[p->netfn>>1]));
  770. if (!ret && p->command >= 0) {
  771. ret = _get_subfn_support(intf, p,
  772. &(bmc->lun[p->lun].netfn[p->netfn>>1].command[p->command]));
  773. ret |= _get_subfn_configurable(intf, p,
  774. &(bmc->lun[p->lun].netfn[p->netfn>>1].command[p->command]));
  775. ret |= _get_subfn_enables(intf, p,
  776. &(bmc->lun[p->lun].netfn[p->netfn>>1].command[p->command]));
  777. }
  778. }
  779. else if (p->lun >= 0) {
  780. l = p->lun;
  781. if (bmc->lun[l].support) {
  782. for (n=0; n<MAX_NETFN_PAIR; n++) {
  783. p->netfn = n*2;
  784. if (bmc->lun[l].netfn[n].support) {
  785. ret = _get_command_support(intf, p, &(bmc->lun[l].netfn[n]));
  786. ret |= _get_command_configurable(intf, p, &(bmc->lun[l].netfn[n]));
  787. ret |= _get_command_enables(intf, p, &(bmc->lun[l].netfn[n]));
  788. }
  789. if (ret)
  790. bmc->lun[l].netfn[n].support = 0;
  791. }
  792. }
  793. p->netfn = -1;
  794. } else {
  795. for (l=0; l<4; l++) {
  796. p->lun = l;
  797. if (bmc->lun[l].support) {
  798. for (n=0; n<MAX_NETFN_PAIR; n++) {
  799. p->netfn = n*2;
  800. if (bmc->lun[l].netfn[n].support) {
  801. ret = _get_command_support(intf, p, &(bmc->lun[l].netfn[n]));
  802. ret |= _get_command_configurable(intf, p, &(bmc->lun[l].netfn[n]));
  803. ret |= _get_command_enables(intf, p, &(bmc->lun[l].netfn[n]));
  804. }
  805. if (ret)
  806. bmc->lun[l].netfn[n].support = 0;
  807. }
  808. }
  809. }
  810. p->lun = -1;
  811. p->netfn = -1;
  812. }
  813. return 0;
  814. }
  815. /* ipmi_firewall_info - print out info for firewall functions
  816. *
  817. * @intf: ipmi inteface
  818. * @argc: argument count
  819. * @argv: argument list
  820. *
  821. * returns 0 on success
  822. * returns -1 on error
  823. */
  824. static int
  825. ipmi_firewall_info(struct ipmi_intf * intf, int argc, char ** argv)
  826. {
  827. int ret = 0;
  828. struct ipmi_function_params p = {0xe, -1, -1, -1, -1, 0};
  829. struct bmc_fn_support * bmc_fn_support;
  830. unsigned int l, n, c;
  831. if ((argc > 0 && strncmp(argv[0], "help", 4) == 0) || ipmi_firewall_parse_args(argc, argv, &p) < 0)
  832. {
  833. printf_firewall_info_usage();
  834. return 0;
  835. }
  836. bmc_fn_support = malloc(sizeof(struct bmc_fn_support));
  837. if (!bmc_fn_support) {
  838. lprintf(LOG_ERR, "malloc struct bmc_fn_support failed");
  839. return -1;
  840. }
  841. ret = _gather_info(intf, &p, bmc_fn_support);
  842. if (p.command >= 0) {
  843. struct command_support * cmd;
  844. if (!((p.lun < 0 || bmc_fn_support->lun[p.lun].support) &&
  845. (p.netfn < 0 || bmc_fn_support->lun[p.lun].netfn[p.netfn>>1].support) &&
  846. bmc_fn_support->lun[p.lun].netfn[p.netfn>>1].command[p.command].support))
  847. {
  848. lprintf(LOG_ERR, "Command 0x%02x not supported on LUN/NetFn pair %02x,%02x",
  849. p.command, p.lun, p.netfn);
  850. free(bmc_fn_support);
  851. bmc_fn_support = NULL;
  852. return 0;
  853. }
  854. cmd =
  855. &bmc_fn_support->lun[p.lun].netfn[p.netfn>>1].command[p.command];
  856. c = cmd->support;
  857. printf("(A)vailable, (C)onfigurable, (E)nabled: | A | C | E |\n");
  858. printf("-----------------------------------------------------\n");
  859. printf("LUN %01d, NetFn 0x%02x, Command 0x%02x: | %c | %c | %c |\n",
  860. p.lun, p.netfn, p.command,
  861. (c & BIT_AVAILABLE) ? 'X' : ' ',
  862. (c & BIT_CONFIGURABLE) ? 'X' : ' ',
  863. (c & BIT_ENABLED) ? 'X': ' ');
  864. for (n=0; n<MAX_SUBFN; n++) {
  865. printf("sub-function 0x%02x: | %c | %c | %c |\n", n,
  866. (!bit_test(cmd->subfn_support, n)) ? 'X' : ' ',
  867. (bit_test(cmd->subfn_config, n)) ? 'X' : ' ',
  868. (bit_test(cmd->subfn_enable, n)) ? 'X' : ' ');
  869. }
  870. }
  871. else if (p.netfn >= 0) {
  872. if (!((p.lun < 0 || bmc_fn_support->lun[p.lun].support) &&
  873. (bmc_fn_support->lun[p.lun].netfn[p.netfn>>1].support)))
  874. {
  875. lprintf(LOG_ERR, "LUN or LUN/NetFn pair %02x,%02x not supported",
  876. p.lun, p.netfn);
  877. free(bmc_fn_support);
  878. bmc_fn_support = NULL;
  879. return 0;
  880. }
  881. n = p.netfn >> 1;
  882. l = p.lun;
  883. printf("Commands on LUN 0x%02x, NetFn 0x%02x\n", p.lun, p.netfn);
  884. printf("support: ");
  885. print_bitfield(bmc_fn_support->lun[l].netfn[n].command_mask,
  886. MAX_COMMAND_BYTES, 1, -1);
  887. printf("configurable: ");
  888. print_bitfield(bmc_fn_support->lun[l].netfn[n].config_mask,
  889. MAX_COMMAND_BYTES, 0, -1);
  890. printf("enabled: ");
  891. print_bitfield(bmc_fn_support->lun[l].netfn[n].enable_mask,
  892. MAX_COMMAND_BYTES, 0, -1);
  893. }
  894. else {
  895. for (l=0; l<4; l++) {
  896. p.lun = l;
  897. if (bmc_fn_support->lun[l].support) {
  898. for (n=0; n<MAX_NETFN_PAIR; n++) {
  899. p.netfn = n*2;
  900. if (bmc_fn_support->lun[l].netfn[n].support) {
  901. printf("%02x,%02x support: ", p.lun, p.netfn);
  902. print_bitfield(bmc_fn_support->lun[l].netfn[n].command_mask,
  903. MAX_COMMAND_BYTES, 1, -1);
  904. printf("%02x,%02x configurable: ", p.lun, p.netfn);
  905. print_bitfield(bmc_fn_support->lun[l].netfn[n].config_mask,
  906. MAX_COMMAND_BYTES, 0, -1);
  907. printf("%02x,%02x enabled: ", p.lun, p.netfn);
  908. print_bitfield(bmc_fn_support->lun[l].netfn[n].enable_mask,
  909. MAX_COMMAND_BYTES, 0, -1);
  910. }
  911. }
  912. }
  913. }
  914. p.lun = -1;
  915. p.netfn = -1;
  916. }
  917. free(bmc_fn_support);
  918. bmc_fn_support = NULL;
  919. return ret;
  920. }
  921. /* ipmi_firewall_enable_disable - enable/disable BMC functions
  922. *
  923. * @intf: ipmi inteface
  924. * @enable: whether to enable or disable
  925. * @argc: argument count
  926. * @argv: argument list
  927. *
  928. * returns 0 on success
  929. * returns -1 on error
  930. */
  931. static int
  932. ipmi_firewall_enable_disable(struct ipmi_intf * intf, int enable, int argc, char ** argv)
  933. {
  934. struct ipmi_function_params p = {0xe, -1, -1, -1, -1, 0};
  935. struct bmc_fn_support * bmc_fn_support;
  936. int ret;
  937. unsigned int l, n, c;
  938. unsigned char enables[MAX_COMMAND_BYTES];
  939. if (argc < 1 || strncmp(argv[0], "help", 4) == 0) {
  940. char * s1 = enable?"en":"dis";
  941. char * s2 = enable?"":" [force]";
  942. printf("%sable [channel H] lun L netfn N%s\n", s1, s2);
  943. printf("\t%sable all commands on this LUN/NetFn pair\n", s1);
  944. printf("%sable [channel H] lun L netfn N command C%s\n", s1, s2);
  945. printf("\t%sable Command C and all its Sub-functions for this LUN/NetFn pair\n", s1);
  946. printf("%sable [channel H] lun L netfn N command C subfn S\n", s1);
  947. printf("\t%sable Sub-function S for Command C for this LUN/NetFn pair\n", s1);
  948. if (!enable) {
  949. printf("* force will allow you to disable the \"Command Set Enable\" command\n");
  950. printf("\tthereby letting you shoot yourself in the foot\n");
  951. printf("\tthis is only recommended for advanced users\n");
  952. }
  953. return 0;
  954. }
  955. if (ipmi_firewall_parse_args(argc, argv, &p) < 0)
  956. return -1;
  957. bmc_fn_support = malloc(sizeof(struct bmc_fn_support));
  958. if (!bmc_fn_support) {
  959. lprintf(LOG_ERR, "malloc struct bmc_fn_support failed");
  960. return -1;
  961. }
  962. ret = _gather_info(intf, &p, bmc_fn_support);
  963. if (ret < 0) {
  964. free(bmc_fn_support);
  965. bmc_fn_support = NULL;
  966. return ret;
  967. }
  968. l = p.lun;
  969. n = p.netfn>>1;
  970. c = p.command;
  971. if (p.subfn >= 0) {
  972. // firewall (en|dis)able [channel c] lun l netfn n command m subfn s
  973. // (en|dis)able this sub-function for this commnad on this lun/netfn pair
  974. memcpy(enables,
  975. bmc_fn_support->lun[l].netfn[n].command[c].subfn_enable,
  976. MAX_SUBFN_BYTES);
  977. bit_set(enables, p.subfn, enable);
  978. ret = _set_subfn_enables(intf, &p,
  979. &bmc_fn_support->lun[l].netfn[n].command[c], enables);
  980. } else if (p.command >= 0) {
  981. // firewall (en|dis)able [channel c] lun l netfn n command m
  982. // (en|dis)able all subfn and command for this commnad on this lun/netfn pair
  983. memset(enables, enable?0xff:0, MAX_SUBFN_BYTES);
  984. ret = _set_subfn_enables(intf, &p,
  985. &bmc_fn_support->lun[l].netfn[n].command[c], enables);
  986. memcpy(enables,
  987. &bmc_fn_support->lun[l].netfn[n].enable_mask, sizeof(enables));
  988. bit_set(enables, p.command, enable);
  989. ret |= _set_command_enables(intf, &p,
  990. &bmc_fn_support->lun[l].netfn[n], enables, p.force);
  991. } else if (p.netfn >= 0) {
  992. // firewall (en|dis)able [channel c] lun l netfn n
  993. // (en|dis)able all commnads on this lun/netfn pair
  994. memset(enables, enable?0xff:0, sizeof(enables));
  995. ret = _set_command_enables(intf, &p,
  996. &bmc_fn_support->lun[l].netfn[n], enables, p.force);
  997. /*
  998. } else if (p.lun >= 0) {
  999. // firewall (en|dis)able [channel c] lun l
  1000. // (en|dis)able all commnads on all netfn pairs for this lun
  1001. */
  1002. }
  1003. free(bmc_fn_support);
  1004. bmc_fn_support = NULL;
  1005. return ret;
  1006. }
  1007. /* ipmi_firewall_reset - reset firmware firewall to enable everything
  1008. *
  1009. * @intf: ipmi inteface
  1010. * @argc: argument count
  1011. * @argv: argument list
  1012. *
  1013. * returns 0 on success
  1014. * returns -1 on error
  1015. */
  1016. static int
  1017. ipmi_firewall_reset(struct ipmi_intf * intf, int argc, char ** argv)
  1018. {
  1019. struct ipmi_function_params p = {0xe, -1, -1, -1, -1, 0};
  1020. struct bmc_fn_support * bmc_fn_support;
  1021. int ret;
  1022. unsigned int l, n, c;
  1023. unsigned char enables[MAX_COMMAND_BYTES];
  1024. if (argc < 1) {
  1025. lprintf(LOG_ERR, "Not enough parameters given.");
  1026. printf_firewall_usage();
  1027. return (-1);
  1028. } else if (argc > 0 && strncmp(argv[0], "help", 4) == 0) {
  1029. printf_firewall_usage();
  1030. return 0;
  1031. }
  1032. if (ipmi_firewall_parse_args(argc, argv, &p) < 0)
  1033. return -1;
  1034. bmc_fn_support = malloc(sizeof(struct bmc_fn_support));
  1035. if (!bmc_fn_support) {
  1036. lprintf(LOG_ERR, "malloc struct bmc_fn_support failed");
  1037. return -1;
  1038. }
  1039. ret = _gather_info(intf, &p, bmc_fn_support);
  1040. if (ret < 0) {
  1041. free(bmc_fn_support);
  1042. bmc_fn_support = NULL;
  1043. return ret;
  1044. }
  1045. for (l=0; l<MAX_LUN; l++) {
  1046. p.lun = l;
  1047. for (n=0; n<MAX_NETFN_PAIR; n++) {
  1048. p.netfn = n*2;
  1049. for (c=0; c<MAX_COMMAND; c++) {
  1050. p.command = c;
  1051. printf("reset lun %d, netfn %d, command %d, subfn\n", l, n, c);
  1052. memset(enables, 0xff, MAX_SUBFN_BYTES);
  1053. ret = _set_subfn_enables(intf, &p,
  1054. &bmc_fn_support->lun[l].netfn[n].command[c], enables);
  1055. }
  1056. printf("reset lun %d, netfn %d, command\n", l, n);
  1057. memset(enables, 0xff, sizeof(enables));
  1058. ret = _set_command_enables(intf, &p,
  1059. &bmc_fn_support->lun[l].netfn[n], enables, 0);
  1060. }
  1061. }
  1062. free(bmc_fn_support);
  1063. bmc_fn_support = NULL;
  1064. return ret;
  1065. }
  1066. /* ipmi_firewall_main - top-level handler for firmware firewall functions
  1067. *
  1068. * @intf: ipmi interface
  1069. * @argc: number of arguments
  1070. * @argv: argument list
  1071. *
  1072. * returns 0 on success
  1073. * returns -1 on error
  1074. */
  1075. int
  1076. ipmi_firewall_main(struct ipmi_intf * intf, int argc, char ** argv)
  1077. {
  1078. int rc = 0;
  1079. if (argc < 1 || strncmp(argv[0], "help", 4) == 0) {
  1080. printf_firewall_usage();
  1081. }
  1082. else if (strncmp(argv[0], "info", 4) == 0) {
  1083. rc = ipmi_firewall_info(intf, argc-1, &(argv[1]));
  1084. }
  1085. else if (strncmp(argv[0], "enable", 6) == 0) {
  1086. rc = ipmi_firewall_enable_disable(intf, 1, argc-1, &(argv[1]));
  1087. }
  1088. else if (strncmp(argv[0], "disable", 7) == 0) {
  1089. rc = ipmi_firewall_enable_disable(intf, 0, argc-1, &(argv[1]));
  1090. }
  1091. else if (strncmp(argv[0], "reset", 5) == 0) {
  1092. rc = ipmi_firewall_reset(intf, argc-1, &(argv[1]));
  1093. }
  1094. else {
  1095. printf_firewall_usage();
  1096. }
  1097. return rc;
  1098. }