1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431 |
- /*
- * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind.
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
- * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
- * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
- * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
- * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
- * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
- * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
- * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
- * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- */
- #define _XOPEN_SOURCE
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <strings.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <errno.h>
- #include <time.h>
- #include <unistd.h>
- #include <signal.h>
- #include <ctype.h>
- #include <sys/time.h>
- #include <limits.h>
- #include <fcntl.h>
- #include <sys/select.h>
- #include <termios.h>
- #include <ipmitool/ipmi.h>
- #include <ipmitool/ipmi_intf.h>
- #include <ipmitool/helper.h>
- #include <ipmitool/log.h>
- #include <ipmitool/ipmi_sel.h>
- #include <ipmitool/ipmi_sdr.h>
- #include <ipmitool/ipmi_strings.h>
- #include <ipmitool/ipmi_channel.h>
- #include <ipmitool/ipmi_sunoem.h>
- #include <ipmitool/ipmi_raw.h>
- static const struct valstr sunoem_led_type_vals[] = {
- { 0, "OK2RM" },
- { 1, "SERVICE" },
- { 2, "ACT" },
- { 3, "LOCATE" },
- { 0xFF, NULL },
- };
- static const struct valstr sunoem_led_mode_vals[] = {
- { 0, "OFF" },
- { 1, "ON" },
- { 2, "STANDBY" },
- { 3, "SLOW" },
- { 4, "FAST" },
- { 0xFF, NULL },
- };
- static const struct valstr sunoem_led_mode_optvals[] = {
- { 0, "STEADY_OFF" },
- { 1, "STEADY_ON" },
- { 2, "STANDBY_BLINK" },
- { 3, "SLOW_BLINK" },
- { 4, "FAST_BLINK" },
- { 0xFF, NULL },
- };
- #define SUNOEM_SUCCESS 1
- #define IPMI_SUNOEM_GETFILE_VERSION {3,2,0,0}
- #define IPMI_SUNOEM_GETBEHAVIOR_VERSION {3,2,0,0}
- /*
- * PRINT_NORMAL: print out the LED value as normal
- * PRINT_ERROR: print out "na" for the LED value
- */
- typedef enum
- {
- PRINT_NORMAL = 0, PRINT_ERROR
- } print_status_t;
- int ret_get = 0;
- int ret_set = 0;
- static void
- ipmi_sunoem_usage(void)
- {
- lprintf(LOG_NOTICE, "Usage: sunoem <command> [option...]");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, "Commands:");
- lprintf(LOG_NOTICE, " - cli [<command string> ...]");
- lprintf(LOG_NOTICE, " Execute SP CLI commands.");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, " - led get [<sensor_id>] [ledtype]");
- lprintf(LOG_NOTICE, " - Read status of LED found in Generic Device Locator.");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, " - led set <sensor_id> <led_mode> [led_type]");
- lprintf(LOG_NOTICE, " - Set mode of LED found in Generic Device Locator.");
- lprintf(LOG_NOTICE, " - You can pass 'all' as the <senso_rid> to change the LED mode of all sensors.");
- lprintf(LOG_NOTICE, " - Use 'sdr list generic' command to get list of Generic");
- lprintf(LOG_NOTICE, " - Devices that are controllable LEDs.");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, " - Required SIS LED Mode:");
- lprintf(LOG_NOTICE, " OFF Off");
- lprintf(LOG_NOTICE, " ON Steady On");
- lprintf(LOG_NOTICE, " STANDBY 100ms on 2900ms off blink rate");
- lprintf(LOG_NOTICE, " SLOW 1HZ blink rate");
- lprintf(LOG_NOTICE, " FAST 4HZ blink rate");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, " - Optional SIS LED Type:");
- lprintf(LOG_NOTICE, " OK2RM OK to Remove");
- lprintf(LOG_NOTICE, " SERVICE Service Required");
- lprintf(LOG_NOTICE, " ACT Activity");
- lprintf(LOG_NOTICE, " LOCATE Locate");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, " - nacname <ipmi_nac_name>");
- lprintf(LOG_NOTICE, " - Returns the full nac name");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, " - ping NUMBER <q>");
- lprintf(LOG_NOTICE, " - Send and Receive NUMBER (64 Byte) packets.");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, " - q - Quiet. Displays output at start and end");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, " - getval <target_name>");
- lprintf(LOG_NOTICE, " - Returns the ILOM property value");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, " - setval <property name> <property value> <timeout>");
- lprintf(LOG_NOTICE, " - Sets the ILOM property value");
- lprintf(LOG_NOTICE, " - If timeout is not specified, the default is 5 sec.");
- lprintf(LOG_NOTICE, " - NOTE: must be executed locally on host, not remotely over LAN!");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, " - sshkey del <user_id>");
- lprintf(LOG_NOTICE, " - Delete ssh key for user id from authorized_keys,");
- lprintf(LOG_NOTICE, " - view users with 'user list' command.");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, " - sshkey set <user_id> <id_rsa.pub>");
- lprintf(LOG_NOTICE, " - Set ssh key for a userid into authorized_keys,");
- lprintf(LOG_NOTICE, " - view users with 'user list' command.");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, " - version");
- lprintf(LOG_NOTICE, " - Display the software version");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, " - nacname <ipmi_nac_name>");
- lprintf(LOG_NOTICE, " - Returns the full nac name");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, " - getfile <file_string_id> <destination_file_name>");
- lprintf(LOG_NOTICE, " - Copy file <file_string_id> to <destination_file_name>");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, " - File string ids:");
- lprintf(LOG_NOTICE, " SSH_PUBKEYS");
- lprintf(LOG_NOTICE, " DIAG_PASSED");
- lprintf(LOG_NOTICE, " DIAG_FAILED");
- lprintf(LOG_NOTICE, " DIAG_END_TIME");
- lprintf(LOG_NOTICE, " DIAG_INVENTORY");
- lprintf(LOG_NOTICE, " DIAG_TEST_LOG");
- lprintf(LOG_NOTICE, " DIAG_START_TIME");
- lprintf(LOG_NOTICE, " DIAG_UEFI_LOG");
- lprintf(LOG_NOTICE, " DIAG_TEST_LOG");
- lprintf(LOG_NOTICE, " DIAG_LAST_LOG");
- lprintf(LOG_NOTICE, " DIAG_LAST_CMD");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, " - getbehavior <behavior_string_id>");
- lprintf(LOG_NOTICE, " - Test if ILOM behavior is enabled");
- lprintf(LOG_NOTICE, "");
- lprintf(LOG_NOTICE, " - Behavior string ids:");
- lprintf(LOG_NOTICE, " SUPPORTS_SIGNED_PACKAGES");
- lprintf(LOG_NOTICE, " REQUIRES_SIGNED_PACKAGES");
- lprintf(LOG_NOTICE, "");
- }
- #define SUNOEM_FAN_MODE_AUTO 0x00
- #define SUNOEM_FAN_MODE_MANUAL 0x01
- static void
- __sdr_list_empty(struct sdr_record_list * head)
- {
- struct sdr_record_list * e, *f;
- for (e = head; e != NULL; e = f) {
- f = e->next;
- free(e);
- }
- head = NULL;
- }
- /*
- * led_print
- * Print out the led name and the state, if stat is PRINT_NORMAL.
- * Otherwise, print out the led name and "na".
- * The state parameter is not referenced if stat is not PRINT_NORMAL.
- */
- static void
- led_print(const char * name, print_status_t stat, uint8_t state)
- {
- const char *theValue;
- if (stat == PRINT_NORMAL) {
- theValue = val2str(state, sunoem_led_mode_vals);
- } else {
- theValue = "na";
- }
- if (csv_output) {
- printf("%s,%s\n", name, theValue);
- } else {
- printf("%-16s | %s\n", name, theValue);
- }
- }
- #define CC_NORMAL 0x00
- #define CC_PARAM_OUT_OF_RANGE 0xc9
- #define CC_DEST_UNAVAILABLE 0xd3
- #define CC_UNSPECIFIED_ERR 0xff
- #define CC_INSUFFICIENT_PRIVILEGE 0xd4
- #define CC_INV_CMD 0xc1
- #define CC_INV_DATA_FIELD 0xcc
- /*
- * sunoem_led_get(....)
- *
- * OUTPUT:
- * SUNOEM_EC_INVALID_ARG if dev is NULL,
- * SUNOEM_EC_BMC_NOT_RESPONDING if no reply is obtained from BMC,
- * SUNOEM_EC_BMC_CCODE_NONZERO if completion code is nonzero,
- * SUNOEM_EC_SUCCESS otherwise.
- */
- static sunoem_ec_t
- sunoem_led_get(struct ipmi_intf * intf, struct sdr_record_generic_locator * dev,
- int ledtype, struct ipmi_rs **loc_rsp)
- {
- struct ipmi_rs * rsp;
- struct ipmi_rq req;
- uint8_t rqdata[7];
- int rqdata_len;
- if (dev == NULL) {
- *loc_rsp = NULL;
- return (SUNOEM_EC_INVALID_ARG);
- }
- rqdata[0] = dev->dev_slave_addr;
- if (ledtype == 0xFF)
- rqdata[1] = dev->oem;
- else
- rqdata[1] = ledtype;
- rqdata[2] = dev->dev_access_addr;
- rqdata[3] = dev->oem;
- rqdata[4] = dev->entity.id;
- rqdata[5] = dev->entity.instance;
- rqdata[6] = 0;
- rqdata_len = 7;
- req.msg.netfn = IPMI_NETFN_SUNOEM;
- req.msg.cmd = IPMI_SUNOEM_LED_GET;
- req.msg.lun = dev->lun;
- req.msg.data = rqdata;
- req.msg.data_len = rqdata_len;
- rsp = intf->sendrecv(intf, &req);
- /*
- * Just return NULL if there was
- * an error.
- */
- if (rsp == NULL) {
- *loc_rsp = NULL;
- return (SUNOEM_EC_BMC_NOT_RESPONDING);
- } else if (rsp->ccode > 0) {
- *loc_rsp = rsp;
- return (SUNOEM_EC_BMC_CCODE_NONZERO);
- } else {
- *loc_rsp = rsp;
- return (SUNOEM_EC_SUCCESS);
- }
- }
- static struct ipmi_rs *
- sunoem_led_set(struct ipmi_intf * intf, struct sdr_record_generic_locator * dev,
- int ledtype, int ledmode)
- {
- struct ipmi_rs * rsp;
- struct ipmi_rq req;
- uint8_t rqdata[9];
- int rqdata_len;
- if (dev == NULL)
- return NULL;
- rqdata[0] = dev->dev_slave_addr;
- if (ledtype == 0xFF)
- rqdata[1] = dev->oem;
- else
- rqdata[1] = ledtype;
- rqdata[2] = dev->dev_access_addr;
- rqdata[3] = dev->oem;
- rqdata[4] = ledmode;
- rqdata[5] = dev->entity.id;
- rqdata[6] = dev->entity.instance;
- rqdata[7] = 0;
- rqdata[8] = 0;
- rqdata_len = 9;
- req.msg.netfn = IPMI_NETFN_SUNOEM;
- req.msg.cmd = IPMI_SUNOEM_LED_SET;
- req.msg.lun = dev->lun;
- req.msg.data = rqdata;
- req.msg.data_len = rqdata_len;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Sun OEM Set LED command failed.");
- return NULL;
- } else if (rsp->ccode > 0) {
- lprintf(LOG_ERR, "Sun OEM Set LED command failed: %s",
- val2str(rsp->ccode, completion_code_vals));
- return NULL;
- }
- return (rsp);
- }
- static void
- sunoem_led_get_byentity(struct ipmi_intf * intf, uint8_t entity_id,
- uint8_t entity_inst, int ledtype)
- {
- struct ipmi_rs * rsp;
- struct sdr_record_list *elist, *e;
- struct entity_id entity;
- sunoem_ec_t res;
- if (entity_id == 0)
- return;
- /* lookup sdrs with this entity */
- memset(&entity, 0, sizeof(struct entity_id));
- entity.id = entity_id;
- entity.instance = entity_inst;
- elist = ipmi_sdr_find_sdr_byentity(intf, &entity);
- if (elist == NULL)
- ret_get = -1;
- /* for each generic sensor get its led state */
- for (e = elist; e != NULL; e = e->next) {
- if (e->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
- continue;
- res = sunoem_led_get(intf, e->record.genloc, ledtype, &rsp);
- if (res == SUNOEM_EC_SUCCESS && rsp && rsp->data_len == 1) {
- led_print((const char *) e->record.genloc->id_string, PRINT_NORMAL,
- rsp->data[0]);
- } else {
- led_print((const char *) e->record.genloc->id_string, PRINT_ERROR,
- 0);
- if (res != SUNOEM_EC_BMC_CCODE_NONZERO|| !rsp
- || rsp->ccode != CC_DEST_UNAVAILABLE) {
- ret_get = -1;
- }
- }
- }
- __sdr_list_empty(elist);
- }
- static void
- sunoem_led_set_byentity(struct ipmi_intf * intf, uint8_t entity_id,
- uint8_t entity_inst, int ledtype, int ledmode)
- {
- struct ipmi_rs * rsp;
- struct sdr_record_list *elist, *e;
- struct entity_id entity;
- if (entity_id == 0)
- return;
- /* lookup sdrs with this entity */
- memset(&entity, 0, sizeof(struct entity_id));
- entity.id = entity_id;
- entity.instance = entity_inst;
- elist = ipmi_sdr_find_sdr_byentity(intf, &entity);
- if (elist == NULL)
- ret_set = -1;
- /* for each generic sensor set its led state */
- for (e = elist; e != NULL; e = e->next) {
- if (e->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
- continue;
- rsp = sunoem_led_set(intf, e->record.genloc, ledtype, ledmode);
- if (rsp && rsp->data_len == 0) {
- led_print((const char *) e->record.genloc->id_string, PRINT_NORMAL,
- ledmode);
- } else if (rsp == NULL) {
- ret_set = -1;
- }
- }
- __sdr_list_empty(elist);
- }
- /*
- * IPMI Request Data: 5 bytes
- *
- * [byte 0] devAddr Value from the "Device Slave Address" field in
- * LED's Generic Device Locator record in the SDR
- * [byte 1] led LED Type: OK2RM, ACT, LOCATE, SERVICE
- * [byte 2] ctrlrAddr Controller address; value from the "Device
- * Access Address" field, 0x20 if the LED is local
- * [byte 3] hwInfo The OEM field from the SDR record
- * [byte 4] force 1 = directly access the device
- * 0 = go thru its controller
- * Ignored if LED is local
- *
- * The format below is for Sun Blade Modular systems only
- * [byte 4] entityID The entityID field from the SDR record
- * [byte 5] entityIns The entityIns field from the SDR record
- * [byte 6] force 1 = directly access the device
- * 0 = go thru its controller
- * Ignored if LED is local
- */
- static int
- ipmi_sunoem_led_get(struct ipmi_intf * intf, int argc, char ** argv)
- {
- struct ipmi_rs * rsp;
- struct sdr_record_list *sdr;
- struct sdr_record_list *alist, *a;
- struct sdr_record_entity_assoc *assoc;
- int ledtype = 0xFF;
- int i;
- sunoem_ec_t res;
- /*
- * sunoem led/sbled get <id> [type]
- */
- if (argc < 1 || strncmp(argv[0], "help", 4) == 0) {
- ipmi_sunoem_usage();
- return (0);
- }
- if (argc > 1) {
- ledtype = str2val(argv[1], sunoem_led_type_vals);
- if (ledtype == 0xFF)
- lprintf(LOG_ERR,
- "Unknown ledtype, will use data from the SDR oem field");
- }
- if (strncasecmp(argv[0], "all", 3) == 0) {
- /* do all generic sensors */
- alist = ipmi_sdr_find_sdr_bytype(intf,
- SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR);
- if (alist == NULL)
- return (-1);
- for (a = alist; a != NULL; a = a->next) {
- if (a->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
- continue;
- if (a->record.genloc->entity.logical)
- continue;
- res = sunoem_led_get(intf, a->record.genloc, ledtype, &rsp);
- if (res == SUNOEM_EC_SUCCESS && rsp && rsp->data_len == 1) {
- led_print((const char *) a->record.genloc->id_string,
- PRINT_NORMAL, rsp->data[0]);
- } else {
- led_print((const char *) a->record.genloc->id_string,
- PRINT_ERROR, 0);
- if (res != SUNOEM_EC_BMC_CCODE_NONZERO|| !rsp ||
- rsp->ccode != CC_DEST_UNAVAILABLE) {
- ret_get = -1;
- }
- }
- }
- __sdr_list_empty(alist);
- if (ret_get == -1)
- return (-1);
- return (0);
- }
- /* look up generic device locator record in SDR */
- sdr = ipmi_sdr_find_sdr_byid(intf, argv[0]);
- if (sdr == NULL) {
- lprintf(LOG_ERR, "No Sensor Data Record found for %s", argv[0]);
- return (-1);
- }
- if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) {
- lprintf(LOG_ERR, "Invalid SDR type %d", sdr->type);
- return (-1);
- }
- if (!sdr->record.genloc->entity.logical) {
- /*
- * handle physical entity
- */
- res = sunoem_led_get(intf, sdr->record.genloc, ledtype, &rsp);
- if (res == SUNOEM_EC_SUCCESS && rsp && rsp->data_len == 1) {
- led_print((const char *) sdr->record.genloc->id_string,
- PRINT_NORMAL, rsp->data[0]);
- } else {
- led_print((const char *) sdr->record.genloc->id_string, PRINT_ERROR,
- 0);
- if (res != SUNOEM_EC_BMC_CCODE_NONZERO|| !rsp
- || rsp->ccode != CC_DEST_UNAVAILABLE) {
- ret_get = -1;
- }
- }
- if (ret_get == -1)
- return (-1);
- return (0);
- }
- /*
- * handle logical entity for LED grouping
- */
- lprintf(LOG_INFO, "LED %s is logical device", argv[0]);
- /* get entity assoc records */
- alist = ipmi_sdr_find_sdr_bytype(intf, SDR_RECORD_TYPE_ENTITY_ASSOC);
- if (alist == NULL)
- return (-1);
- for (a = alist; a != NULL; a = a->next) {
- if (a->type != SDR_RECORD_TYPE_ENTITY_ASSOC)
- continue;
- assoc = a->record.entassoc;
- if (assoc == NULL)
- continue;
- /* check that the entity id/instance matches our generic record */
- if (assoc->entity.id != sdr->record.genloc->entity.id
- || assoc->entity.instance
- != sdr->record.genloc->entity.instance)
- continue;
- if (assoc->flags.isrange) {
- /*
- * handle ranged entity associations
- *
- * the test for non-zero entity id is handled in
- * sunoem_led_get_byentity()
- */
- /* first range set - id 1 and 2 must be equal */
- if (assoc->entity_id_1 == assoc->entity_id_2)
- for (i = assoc->entity_inst_1; i <= assoc->entity_inst_2; i++)
- sunoem_led_get_byentity(intf, assoc->entity_id_1, i,
- ledtype);
- /* second range set - id 3 and 4 must be equal */
- if (assoc->entity_id_3 == assoc->entity_id_4)
- for (i = assoc->entity_inst_3; i <= assoc->entity_inst_4; i++)
- sunoem_led_get_byentity(intf, assoc->entity_id_3, i,
- ledtype);
- } else {
- /*
- * handle entity list
- */
- sunoem_led_get_byentity(intf, assoc->entity_id_1,
- assoc->entity_inst_1, ledtype);
- sunoem_led_get_byentity(intf, assoc->entity_id_2,
- assoc->entity_inst_2, ledtype);
- sunoem_led_get_byentity(intf, assoc->entity_id_3,
- assoc->entity_inst_3, ledtype);
- sunoem_led_get_byentity(intf, assoc->entity_id_4,
- assoc->entity_inst_4, ledtype);
- }
- }
- __sdr_list_empty(alist);
- if (ret_get == -1)
- return (-1);
- return (0);
- }
- /*
- * IPMI Request Data: 7 bytes
- *
- * [byte 0] devAddr Value from the "Device Slave Address" field in
- * LED's Generic Device Locator record in the SDR
- * [byte 1] led LED Type: OK2RM, ACT, LOCATE, SERVICE
- * [byte 2] ctrlrAddr Controller address; value from the "Device
- * Access Address" field, 0x20 if the LED is local
- * [byte 3] hwInfo The OEM field from the SDR record
- * [byte 4] mode LED Mode: OFF, ON, STANDBY, SLOW, FAST
- * [byte 5] force TRUE - directly access the device
- * FALSE - go thru its controller
- * Ignored if LED is local
- * [byte 6] role Used by BMC for authorization purposes
- *
- * The format below is for Sun Blade Modular systems only
- * [byte 5] entityID The entityID field from the SDR record
- * [byte 6] entityIns The entityIns field from the SDR record
- * [byte 7] force TRUE - directly access the device
- * FALSE - go thru its controller
- * Ignored if LED is local
- * [byte 8] role Used by BMC for authorization purposes
- *
- *
- * IPMI Response Data: 1 byte
- *
- * [byte 0] mode LED Mode: OFF, ON, STANDBY, SLOW, FAST
- */
- static int
- ipmi_sunoem_led_set(struct ipmi_intf * intf, int argc, char ** argv)
- {
- struct ipmi_rs * rsp;
- struct sdr_record_list *sdr;
- struct sdr_record_list *alist, *a;
- struct sdr_record_entity_assoc *assoc;
- int ledmode;
- int ledtype = 0xFF;
- int i;
- /*
- * sunoem led/sbled set <id> <mode> [type]
- */
- if (argc < 2 || strncmp(argv[0], "help", 4) == 0) {
- ipmi_sunoem_usage();
- return (0);
- }
- ledmode = str2val(argv[1], sunoem_led_mode_vals);
- if (ledmode == 0xFF) {
- ledmode = str2val(argv[1], sunoem_led_mode_optvals);
- if (ledmode == 0xFF) {
- lprintf(LOG_NOTICE, "Invalid LED Mode: %s", argv[1]);
- return (-1);
- }
- }
- if (argc > 3) {
- ledtype = str2val(argv[2], sunoem_led_type_vals);
- if (ledtype == 0xFF)
- lprintf(LOG_ERR,
- "Unknown ledtype, will use data from the SDR oem field");
- }
- if (strncasecmp(argv[0], "all", 3) == 0) {
- /* do all generic sensors */
- alist = ipmi_sdr_find_sdr_bytype(intf,
- SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR);
- if (alist == NULL)
- return (-1);
- for (a = alist; a != NULL; a = a->next) {
- if (a->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
- continue;
- if (a->record.genloc->entity.logical)
- continue;
- rsp = sunoem_led_set(intf, a->record.genloc, ledtype, ledmode);
- if (rsp && rsp->ccode == 0)
- led_print((const char *) a->record.genloc->id_string,
- PRINT_NORMAL, ledmode);
- else
- ret_set = -1;
- }
- __sdr_list_empty(alist);
- if (ret_set == -1)
- return (-1);
- return (0);
- }
- /* look up generic device locator records in SDR */
- sdr = ipmi_sdr_find_sdr_byid(intf, argv[0]);
- if (sdr == NULL) {
- lprintf(LOG_ERR, "No Sensor Data Record found for %s", argv[0]);
- return (-1);
- }
- if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) {
- lprintf(LOG_ERR, "Invalid SDR type %d", sdr->type);
- return (-1);
- }
- if (!sdr->record.genloc->entity.logical) {
- /*
- * handle physical entity
- */
- rsp = sunoem_led_set(intf, sdr->record.genloc, ledtype, ledmode);
- if (rsp && rsp->ccode == 0)
- led_print(argv[0], PRINT_NORMAL, ledmode);
- else
- return (-1);
- return (0);
- }
- /*
- * handle logical entity for LED grouping
- */
- lprintf(LOG_INFO, "LED %s is logical device", argv[0]);
- /* get entity assoc records */
- alist = ipmi_sdr_find_sdr_bytype(intf, SDR_RECORD_TYPE_ENTITY_ASSOC);
- if (alist == NULL)
- return (-1);
- for (a = alist; a != NULL; a = a->next) {
- if (a->type != SDR_RECORD_TYPE_ENTITY_ASSOC)
- continue;
- assoc = a->record.entassoc;
- if (assoc == NULL)
- continue;
- /* check that the entity id/instance matches our generic record */
- if (assoc->entity.id != sdr->record.genloc->entity.id
- || assoc->entity.instance
- != sdr->record.genloc->entity.instance)
- continue;
- if (assoc->flags.isrange) {
- /*
- * handle ranged entity associations
- *
- * the test for non-zero entity id is handled in
- * sunoem_led_get_byentity()
- */
- /* first range set - id 1 and 2 must be equal */
- if (assoc->entity_id_1 == assoc->entity_id_2)
- for (i = assoc->entity_inst_1; i <= assoc->entity_inst_2; i++)
- sunoem_led_set_byentity(intf, assoc->entity_id_1, i,
- ledtype, ledmode);
- /* second range set - id 3 and 4 must be equal */
- if (assoc->entity_id_3 == assoc->entity_id_4)
- for (i = assoc->entity_inst_3; i <= assoc->entity_inst_4; i++)
- sunoem_led_set_byentity(intf, assoc->entity_id_3, i,
- ledtype, ledmode);
- } else {
- /*
- * handle entity list
- */
- sunoem_led_set_byentity(intf, assoc->entity_id_1,
- assoc->entity_inst_1, ledtype, ledmode);
- sunoem_led_set_byentity(intf, assoc->entity_id_2,
- assoc->entity_inst_2, ledtype, ledmode);
- sunoem_led_set_byentity(intf, assoc->entity_id_3,
- assoc->entity_inst_3, ledtype, ledmode);
- sunoem_led_set_byentity(intf, assoc->entity_id_4,
- assoc->entity_inst_4, ledtype, ledmode);
- }
- }
- __sdr_list_empty(alist);
- if (ret_set == -1)
- return (-1);
- return (0);
- }
- static int
- ipmi_sunoem_sshkey_del(struct ipmi_intf * intf, uint8_t uid)
- {
- struct ipmi_rs * rsp;
- struct ipmi_rq req;
- memset(&req, 0, sizeof(struct ipmi_rq));
- req.msg.netfn = IPMI_NETFN_SUNOEM;
- req.msg.cmd = IPMI_SUNOEM_DEL_SSH_KEY;
- req.msg.data = &uid;
- req.msg.data_len = 1;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Unable to delete ssh key for UID %d", uid);
- return (-1);
- } else if (rsp->ccode > 0) {
- lprintf(LOG_ERR, "Unable to delete ssh key for UID %d: %s", uid,
- val2str(rsp->ccode, completion_code_vals));
- return (-1);
- }
- printf("Deleted SSH key for user id %d\n", uid);
- return (0);
- }
- #define SSHKEY_BLOCK_SIZE 64
- static int
- ipmi_sunoem_sshkey_set(struct ipmi_intf * intf, uint8_t uid, char * ifile)
- {
- struct ipmi_rs * rsp;
- struct ipmi_rq req;
- FILE * fp;
- int count = 0;
- uint8_t wbuf[SSHKEY_BLOCK_SIZE + 3];
- int32_t i_size = 0;
- int32_t r = 0;
- int32_t size = 0;
- if (ifile == NULL) {
- lprintf(LOG_ERR, "Invalid or misisng input filename.");
- return (-1);
- }
- fp = ipmi_open_file_read(ifile);
- if (fp == NULL) {
- lprintf(LOG_ERR, "Unable to open file '%s' for reading.", ifile);
- return (-1);
- }
- memset(&req, 0, sizeof(struct ipmi_rq));
- req.msg.netfn = IPMI_NETFN_SUNOEM;
- req.msg.cmd = IPMI_SUNOEM_SET_SSH_KEY;
- req.msg.data = wbuf;
- if (fseek(fp, 0, SEEK_END) == (-1)) {
- lprintf(LOG_ERR, "Failed to seek in file '%s'.", ifile);
- if (fp != NULL)
- fclose(fp);
- return (-1);
- }
- size = (int32_t) ftell(fp);
- if (size < 0) {
- lprintf(LOG_ERR, "Failed to seek in file '%s'.", ifile);
- if (fp != NULL)
- fclose(fp);
- return (-1);
- } else if (size == 0) {
- lprintf(LOG_ERR, "File '%s' is empty.", ifile);
- if (fp != NULL)
- fclose(fp);
- return (-1);
- }
- if (fseek(fp, 0, SEEK_SET) == (-1)) {
- lprintf(LOG_ERR, "Failed to seek in file '%s'.", ifile);
- if (fp != NULL)
- fclose(fp);
- return (-1);
- }
- printf("Setting SSH key for user id %d...", uid);
- for (r = 0; r < size; r += i_size) {
- i_size = size - r;
- if (i_size > SSHKEY_BLOCK_SIZE)
- i_size = SSHKEY_BLOCK_SIZE;
- memset(wbuf, 0, SSHKEY_BLOCK_SIZE);
- fseek(fp, r, SEEK_SET);
- count = fread(wbuf + 3, 1, i_size, fp);
- if (count != i_size) {
- printf("failed\n");
- lprintf(LOG_ERR, "Unable to read %ld bytes from file '%s'.", i_size,
- ifile);
- if (fp != NULL)
- fclose(fp);
- return (-1);
- }
- printf(".");
- fflush(stdout);
- wbuf[0] = uid;
- if ((r + SSHKEY_BLOCK_SIZE) >= size)
- wbuf[1] = 0xff;
- else {
- if ((r / SSHKEY_BLOCK_SIZE) > UINT8_MAX) {
- printf("failed\n");
- lprintf(LOG_ERR, "Unable to pack byte %ld from file '%s'.", r,
- ifile);
- if (fp != NULL)
- fclose(fp);
- return (-1);
- }
- wbuf[1] = (uint8_t) (r / SSHKEY_BLOCK_SIZE);
- }
- wbuf[2] = (uint8_t) i_size;
- req.msg.data_len = i_size + 3;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- printf("failed\n");
- lprintf(LOG_ERR, "Unable to set ssh key for UID %d.", uid);
- if (fp != NULL)
- fclose(fp);
- return (-1);
- } /* if (rsp == NULL) */
- if (rsp->ccode != 0) {
- printf("failed\n");
- lprintf(LOG_ERR, "Unable to set ssh key for UID %d, %s.", uid,
- val2str(rsp->ccode, completion_code_vals));
- if (fp != NULL)
- fclose(fp);
- return (-1);
- } /* if (rsp->ccode != 0) */
- }
- printf("done\n");
- fclose(fp);
- return (0);
- }
- /*
- * This structure is used in both the request to and response from the BMC.
- */
- #define SUNOEM_CLI_LEGACY_VERSION 1
- #define SUNOEM_CLI_SEQNUM_VERSION 2
- #define SUNOEM_CLI_VERSION SUNOEM_CLI_SEQNUM_VERSION
- #define SUNOEM_CLI_HEADER 8 /* command + spare + handle */
- #define SUNOEM_CLI_BUF_SIZE (80 - SUNOEM_CLI_HEADER) /* Total 80 bytes */
- #define SUNOEM_CLI_MSG_SIZE(msg) (SUNOEM_CLI_HEADER + strlen((msg).buf) + 1)
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(push, 1)
- #endif
- typedef struct
- {
- /*
- * Set version to SUNOEM_CLI_VERSION.
- */
- uint8_t version;
- /*
- * The command in a request, or in a response indicates an error if
- * non-zero.
- */
- uint8_t command_response;
- uint8_t seqnum;
- uint8_t spare;
- /*
- * Opaque 4-byte handle, supplied in the response to an OPEN request,
- * and used in all subsequent POLL and CLOSE requests.
- */
- uint8_t handle[4];
- /*
- * The client data in a request, or the server data in a response. Must
- * by null terminated, i.e., it must be at least one byte, but can be
- * smaller if there's less data.
- */
- char buf[SUNOEM_CLI_BUF_SIZE];
- }__attribute__((packed)) sunoem_cli_msg_t;
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(pop)
- #endif
- /*
- * Command codes for the command_request field in each request.
- */
- #define SUNOEM_CLI_CMD_OPEN 0 /* Open a new connection */
- #define SUNOEM_CLI_CMD_FORCE 1 /* Close any existing connection, then open */
- #define SUNOEM_CLI_CMD_CLOSE 2 /* Close the current connection */
- #define SUNOEM_CLI_CMD_POLL 3 /* Poll for new data to/from the server */
- #define SUNOEM_CLI_CMD_EOF 4 /* Poll, client is out of data */
- #define SUNOEM_CLI_MAX_RETRY 3 /* Maximum number of retries */
- #define SUNOEM_CLI_INVALID_VER_ERR "Invalid version"
- #define SUNOEM_CLI_BUSY_ERR "Busy"
- typedef enum
- {
- C_CTL_B = 0x02, /* same as left arrow */
- C_CTL_C = 0x03,
- C_CTL_D = 0x04,
- C_CTL_F = 0x06, /* same as right arrow */
- C_CTL_N = 0x0E, /* same as down arrow */
- C_CTL_P = 0x10, /* same as up arrow */
- C_DEL = 0x7f
- } canon_char_t;
- static int
- sunoem_cli_unbufmode_start(FILE *f, struct termios *orig_ts)
- {
- struct termios ts;
- int rc;
- if ((rc = tcgetattr(fileno(f), &ts))) {
- return (rc);
- }
- *orig_ts = ts;
- ts.c_lflag &= ~(ICANON | ECHO | ISIG);
- ts.c_cc[VMIN] = 1;
- if ((rc = tcsetattr(fileno(f), TCSAFLUSH, &ts))) {
- return (rc);
- }
- return (0);
- }
- static int
- sunoem_cli_unbufmode_stop(FILE *f, struct termios *ts)
- {
- int rc;
- if ((rc = tcsetattr(fileno(f), TCSAFLUSH, ts))) {
- return (rc);
- }
- return (0);
- }
- static int
- ipmi_sunoem_cli(struct ipmi_intf * intf, int argc, char *argv[])
- {
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- sunoem_cli_msg_t cli_req;
- sunoem_cli_msg_t *cli_rsp;
- int arg_num = 0;
- int arg_pos = 0;
- time_t wait_time = 0;
- int retries;
- static uint8_t SunOemCliActingVersion = SUNOEM_CLI_VERSION;
- unsigned short first_char = 0; /*first char on the line*/
- struct termios orig_ts;
- int error = 0;
- time_t now = 0;
- int delay = 0;
- /* Prepare to open an SP shell session */
- memset(&cli_req, 0, sizeof(cli_req));
- cli_req.version = SunOemCliActingVersion;
- cli_req.command_response = SUNOEM_CLI_CMD_OPEN;
- if (argc > 0 && strcmp(argv[0], "force") == 0) {
- cli_req.command_response = SUNOEM_CLI_CMD_FORCE;
- argc--;
- argv++;
- }
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_SUNOEM;
- req.msg.cmd = IPMI_SUNOEM_CLI;
- req.msg.data = (uint8_t *) &cli_req;
- req.msg.data_len = SUNOEM_CLI_HEADER + 1;
- retries = 0;
- while (1) {
- cli_req.version = SunOemCliActingVersion;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Sun OEM cli command failed");
- return (-1);
- }
- cli_rsp = (sunoem_cli_msg_t *) rsp->data;
- if ((cli_rsp->command_response != 0) || (rsp->ccode != 0)) {
- if (strncmp(cli_rsp->buf, SUNOEM_CLI_INVALID_VER_ERR,
- sizeof(SUNOEM_CLI_INVALID_VER_ERR) - 1) == 0
- || strncmp(&(cli_rsp->buf[1]), SUNOEM_CLI_INVALID_VER_ERR,
- sizeof(SUNOEM_CLI_INVALID_VER_ERR) - 1) == 0) {
- if (SunOemCliActingVersion == SUNOEM_CLI_VERSION) {
- /* Server doesn't support version SUNOEM_CLI_VERSION
- Fall back to legacy version, and try again*/
- SunOemCliActingVersion = SUNOEM_CLI_LEGACY_VERSION;
- continue;
- }
- /* Server doesn't support legacy version either */
- lprintf(LOG_ERR, "Failed to connect: %s", cli_rsp->buf);
- return (-1);
- } else if (strncmp(cli_rsp->buf, SUNOEM_CLI_BUSY_ERR,
- sizeof(SUNOEM_CLI_BUSY_ERR) - 1) == 0) {
- if (retries++ < SUNOEM_CLI_MAX_RETRY) {
- lprintf(LOG_INFO, "Failed to connect: %s, retrying",
- cli_rsp->buf);
- sleep(2);
- continue;
- }
- lprintf(LOG_ERR, "Failed to connect: %s", cli_rsp->buf);
- return (-1);
- } else {
- lprintf(LOG_ERR, "Failed to connect: %s", cli_rsp->buf);
- return (-1);
- }
- }
- break;
- }
- if (SunOemCliActingVersion == SUNOEM_CLI_SEQNUM_VERSION) {
- /*
- * Bit 1 of seqnum is used as an alternating sequence number
- * to allow a server that supports it to detect when a retry is being sent from the host IPMI driver.
- * Typically when this occurs, the server's last response message would have been dropped.
- * Once the server detects this condition, it will know that it should retry sending the response.
- */
- cli_req.seqnum ^= 0x1;
- }
- printf("Connected. Use ^D to exit.\n");
- fflush(NULL);
- /*
- * Remember the handle provided in the response, and issue a
- * series of "poll" commands to send and get data
- */
- memcpy(cli_req.handle, cli_rsp->handle, 4);
- cli_req.command_response = SUNOEM_CLI_CMD_POLL;
- /*
- * If no arguments make input unbuffered and so interactive
- */
- if (argc == 0) {
- if (sunoem_cli_unbufmode_start(stdin, &orig_ts)) {
- lprintf(LOG_ERR, "Failed to set interactive mode: %s",
- strerror(errno));
- return (-1);
- }
- }
- while (rsp->ccode == 0 && cli_rsp->command_response == 0) {
- int rc = 0;
- int count = 0;
- cli_req.buf[0] = '\0';
- if (argc == 0) {
- /*
- * Accept input from stdin. Use select so we don't hang if
- * there's no input to read. Select timeout is 500 msec.
- */
- struct timeval tv = { 0, 500000 }; /* 500 msec */
- fd_set rfds;
- FD_ZERO(&rfds);
- FD_SET(0, &rfds);
- rc = select(1, &rfds, NULL, NULL, &tv);
- if (rc < 0) {
- /* Select returned an error so close and exit */
- printf("Broken pipe\n");
- cli_req.command_response = SUNOEM_CLI_CMD_CLOSE;
- } else if (rc > 0) {
- /* Read data from stdin */
- count = read(0, cli_req.buf, 1 /* sizeof (cli_req.buf) - 1 */);
- /*
- * If select said there was data but there was nothing to
- * read. This implies user hit ^D.
- * Also handle ^D input when pressed as first char at a new line.
- */
- if (count <= 0 || (first_char && cli_req.buf[0] == C_CTL_D)) {
- cli_req.command_response = SUNOEM_CLI_CMD_EOF;
- count = 0;
- }
- first_char = cli_req.buf[0] == '\n' || cli_req.buf[0] == '\r';
- }
- } else {
- /*
- * Get data from command line arguments
- */
- now = time(NULL);
- if (now < wait_time) {
- /* Do nothing; we're waiting */
- } else if (arg_num >= argc) {
- /* Last arg was sent. Set EOF */
- cli_req.command_response = SUNOEM_CLI_CMD_EOF;
- } else if (strncmp(argv[arg_num], "@wait=", 6) == 0) {
- /* This is a wait command */
- char *s = &argv[arg_num][6];
- delay = 0;
- if (*s != '\0') {
- if (str2int(s, &delay)) {
- delay = 0;
- }
- if (delay < 0) {
- delay = 0;
- }
- }
- wait_time = now + delay;
- arg_num++;
- } else {
- /*
- * Take data from args. It may be that the argument is larger
- * than the request buffer can hold. So pull off BUF_SIZE
- * number of characters at a time. When we've consumed the
- * entire arg, append a newline and advance to the next arg.
- */
- int i;
- char *s = argv[arg_num];
- for (i = arg_pos;
- s[i] != '\0' && count < (SUNOEM_CLI_BUF_SIZE - 2);
- i++, count++) {
- cli_req.buf[count] = s[i];
- }
- if (s[i] == '\0') {
- /* Reached end of the arg string, so append a newline */
- cli_req.buf[count++] = '\n';
- /* Reset pos to 0 and advance to the next arg next time */
- arg_pos = 0;
- arg_num++;
- } else {
- /*
- * Otherwise, there's still more characters in the arg
- * to send, so remember where we left off
- */
- arg_pos = i;
- }
- }
- }
- /*
- * Now send the clients's data (if any) and get data back from the
- * server. Loop while the server is giving us data until we suck
- * it dry.
- */
- do {
- cli_req.buf[count++] = '\0'; /* Terminate the string */
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_SUNOEM;
- req.msg.cmd = 0x19;
- req.msg.data = (uint8_t *) &cli_req;
- req.msg.data_len = SUNOEM_CLI_HEADER + count;
- for (retries = 0; retries <= SUNOEM_CLI_MAX_RETRY; retries++) {
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Communication error.");
- error = 1;
- goto cleanup;
- }
- if (rsp->ccode == IPMI_CC_TIMEOUT) { /* Retry if timed out. */
- if (retries == SUNOEM_CLI_MAX_RETRY) { /* If it's the last retry. */
- lprintf(LOG_ERR, "Excessive timeout.");
- error = 1;
- goto cleanup;
- }
- continue;
- }
- break;
- } /* for (retries = 0; retries <= SUNOEM_CLI_MAX_RETRY; retries++) */
- if (SunOemCliActingVersion == SUNOEM_CLI_SEQNUM_VERSION) {
- cli_req.seqnum ^= 0x1; /* Toggle sequence number after request is sent */
- }
- cli_rsp = (sunoem_cli_msg_t *) rsp->data;
- /* Make sure response string is null terminated */
- cli_rsp->buf[sizeof(cli_rsp->buf) - 1] = '\0';
- printf("%s", cli_rsp->buf);
- fflush(NULL); /* Flush partial lines to stdout */
- count = 0; /* Don't re-send the client's data */
- if (cli_req.command_response == SUNOEM_CLI_CMD_EOF
- && cli_rsp->command_response != 0 && rsp->ccode == 0) {
- cli_rsp->command_response = 1;
- }
- } while (cli_rsp->command_response == 0 && cli_rsp->buf[0] != '\0');
- }
- cleanup:
- /* Restore original input mode if cli was running interactively */
- if (argc == 0) {
- if (sunoem_cli_unbufmode_stop(stdin, &orig_ts)) {
- lprintf(LOG_ERR, "Failed to restore interactive mode: %s",
- strerror(errno));
- return (-1);
- }
- }
- return ((error == 0 && cli_rsp->command_response == SUNOEM_SUCCESS) ? 0 : -1);
- }
- #define ECHO_DATA_SIZE 64
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(push, 1)
- #endif
- typedef struct
- {
- uint16_t seq_num;
- unsigned char data[ECHO_DATA_SIZE];
- }__attribute__((packed)) sunoem_echo_msg_t;
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(pop)
- #endif
- /*
- * Send and receive X packets to the BMC. Each packet has a
- * payload size of (sunoem_echo_msg_t) bytes. Each packet is tagged with a
- * sequence number
- */
- static int
- ipmi_sunoem_echo(struct ipmi_intf * intf, int argc, char *argv[])
- {
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- sunoem_echo_msg_t echo_req;
- sunoem_echo_msg_t *echo_rsp;
- struct timeval start_time;
- struct timeval end_time;
- int rc = 0;
- int received = 0;
- int transmitted = 0;
- int quiet_mode = 0;
- uint16_t num, i, j;
- uint32_t total_time, resp_time, min_time, max_time;
- if (argc < 1) {
- return (1);
- }
- if (argc == 2) {
- if (*(argv[1]) == 'q') {
- quiet_mode = 1;
- } else {
- lprintf(LOG_ERR, "Unknown option '%s' given.", argv[1]);
- return (-1);
- }
- } else if (argc > 2) {
- lprintf(LOG_ERR,
- "Too many parameters given. See help for more information.");
- return (-1);
- }
- /* The number of packets to send/receive */
- if (str2ushort(argv[0], &num) != 0) {
- lprintf(LOG_ERR,
- "Given number of packets is either invalid or out of range.");
- return (-1);
- }
- /* Fill in data packet */
- for (i = 0; i < ECHO_DATA_SIZE; i++) {
- echo_req.data[i] = (uint8_t) i;
- }
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_SUNOEM;
- req.msg.cmd = IPMI_SUNOEM_ECHO;
- req.msg.data = (uint8_t *) &echo_req;
- req.msg.data_len = sizeof(sunoem_echo_msg_t);
- echo_req.seq_num = i;
- min_time = INT_MAX;
- max_time = 0;
- total_time = 0;
- for (i = 0; i < num; i++) {
- echo_req.seq_num = i;
- transmitted++;
- gettimeofday(&start_time, NULL);
- rsp = intf->sendrecv(intf, &req);
- gettimeofday(&end_time, NULL);
- resp_time = ((end_time.tv_sec - start_time.tv_sec) * 1000)
- + ((end_time.tv_usec - start_time.tv_usec) / 1000);
- if ((rsp == NULL) || (rsp->ccode != 0)) {
- lprintf(LOG_ERR, "Sun OEM echo command failed. Seq # %d",
- echo_req.seq_num);
- rc = (-2);
- break;
- }
- echo_rsp = (sunoem_echo_msg_t *) rsp->data;
- /* Test if sequence # is valid */
- if (echo_rsp->seq_num != echo_req.seq_num) {
- printf("Invalid Seq # Expecting %d Received %d\n", echo_req.seq_num,
- echo_rsp->seq_num);
- rc = (-2);
- break;
- }
- /* Test if response length is valid */
- if (rsp->session.msglen == req.msg.data_len) {
- printf("Invalid payload size for seq # %d. "
- "Expecting %d Received %d\n", echo_rsp->seq_num,
- req.msg.data_len, rsp->session.msglen);
- rc = (-2);
- break;
- }
- /* Test if the data is valid */
- for (j = 0; j < ECHO_DATA_SIZE; j++) {
- if (echo_rsp->data[j] != j) {
- printf("Corrupt data packet. Seq # %d Offset %d\n",
- echo_rsp->seq_num, j);
- break;
- }
- } /* for (j = 0; j < ECHO_DATA_SIZE; j++) */
- /* If the for loop terminated early - data is corrupt */
- if (j != ECHO_DATA_SIZE) {
- rc = (-2);
- break;
- }
- /* cumalative time */
- total_time += resp_time;
- /* min time */
- if (resp_time < min_time) {
- min_time = resp_time;
- }
- /* max time */
- if (resp_time > max_time) {
- max_time = resp_time;
- }
- received++;
- if (!quiet_mode) {
- printf("Receive %lu Bytes - Seq. # %d time=%d ms\n",
- sizeof(sunoem_echo_msg_t), echo_rsp->seq_num, resp_time);
- }
- } /* for (i = 0; i < num; i++) */
- printf("%d packets transmitted, %d packets received\n", transmitted,
- received);
- if (received) {
- printf("round-trip min/avg/max = %d/%d/%d ms\n", min_time,
- total_time / received, max_time);
- }
- return (rc);
- } /* ipmi_sunoem_echo(...) */
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(push, 1)
- #endif
- typedef struct
- {
- unsigned char oem_record_ver_num;
- unsigned char major;
- unsigned char minor;
- unsigned char update;
- unsigned char micro;
- char nano[10];
- char revision[10];
- char version[40];
- /*
- * When adding new fields (using the spare bytes),
- * add it immediately after the spare field to
- * ensure backward compatability.
- *
- * e.g. char version[40];
- * unsigned char spare[11];
- * int new_item;
- * } sunoem_version_response_t;
- */
- unsigned char spare[15];
- }__attribute__((packed)) sunoem_version_response_t;
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(pop)
- #endif
- typedef struct
- {
- unsigned char major;
- unsigned char minor;
- unsigned char update;
- unsigned char micro;
- } supported_version_t;
- static int
- ipmi_sunoem_getversion(struct ipmi_intf * intf,
- sunoem_version_response_t **version_rsp)
- {
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_SUNOEM;
- req.msg.cmd = IPMI_SUNOEM_VERSION;
- req.msg.data = NULL;
- req.msg.data_len = 0;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Sun OEM Get SP Version Failed.");
- return (-1);
- }
- if (rsp->ccode != 0) {
- lprintf(LOG_ERR, "Sun OEM Get SP Version Failed: %d", rsp->ccode);
- return (-1);
- }
- *version_rsp = (sunoem_version_response_t *) rsp->data;
- return (0);
- }
- static void
- ipmi_sunoem_print_required_version(const supported_version_t* supp_ver)
- {
- lprintf(LOG_ERR, "Command is not supported by this version of ILOM,"
- " required at least: %d.%d.%d.%d", supp_ver->major, supp_ver->minor,
- supp_ver->update, supp_ver->micro);
- }
- /*
- * Function checks current version result against required version.
- * Returns:
- * - negative value if current ILOM version is smaller than required or
- * in case of error
- * - positive value if current ILOM version is greater than required
- * - 0 if there is an exact ILOM version match
- */
- static int
- ipmi_sunoem_checkversion(struct ipmi_intf * intf, supported_version_t* supp_ver)
- {
- sunoem_version_response_t *version_rsp;
- int i = 1;
- if (ipmi_sunoem_getversion(intf, &version_rsp)) {
- lprintf(LOG_ERR, "Unable to get ILOM version");
- return (-1);
- }
- if (version_rsp->major < supp_ver->major) return (-i);
- if (version_rsp->major > supp_ver->major) return (i);
- /*version_rsp->major == supp_ver->major*/
- ++i;
- if (version_rsp->minor < supp_ver->minor) return (-i);
- if (version_rsp->minor > supp_ver->minor) return (i);
- /*version_rsp->minor == supp_ver->minor*/
- ++i;
- if (version_rsp->update < supp_ver->update) return (-i);
- if (version_rsp->update > supp_ver->update) return (i);
- /*version_rsp->update == supp_ver->update*/
- ++i;
- if (version_rsp->micro < supp_ver->micro) return (-i);
- if (version_rsp->micro > supp_ver->micro) return (i);
- /*version_rsp->micro == supp_ver->micro*/
- return (0);
- }
- /*
- * Extract the SP version data including
- * - major #
- * - minor #
- * - update #
- * - micro #
- * - nano #
- * - Revision/Build #
- */
- static int
- ipmi_sunoem_version(struct ipmi_intf * intf)
- {
- sunoem_version_response_t *version_rsp;
- int rc = ipmi_sunoem_getversion(intf, &version_rsp);
- if (!rc) {
- printf("Version: %s\n", version_rsp->version);
- }
- return (rc);
- }
- /*
- * IPMI Max string length is 16 bytes
- * define in usr/src/common/include/ami/IPMI_SDRRecord.h
- */
- #define MAX_ID_STR_LEN 16
- #define MAX_SUNOEM_NAC_SIZE 64
- #define LUAPI_MAX_OBJ_PATH_LEN 256
- #define LUAPI_MAX_OBJ_VAL_LEN 1024
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(push, 1)
- #endif
- typedef struct
- {
- unsigned char seq_num;
- char nac_name[MAX_SUNOEM_NAC_SIZE];
- }__attribute__((packed)) sunoem_nacname_t;
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(pop)
- #endif
- /*
- * Retrieve the full NAC name of the IPMI target.
- *
- * The returned nac name may be larger than the payload size.
- * In which case, it make take several request/payload to retrieve
- * the entire full path name
- *
- * The initial seq_num is set to 0. If the return seq_num is incremented,
- * only the 1st 72 bytes of the nac name is returned and the caller
- * needs to get the next set of string data.
- * If the returned seq_num is identical to the input seq_num, all data
- * has been returned.
- */
- static int
- ipmi_sunoem_nacname(struct ipmi_intf * intf, int argc, char *argv[])
- {
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- sunoem_nacname_t nacname_req;
- sunoem_nacname_t *nacname_rsp;
- char full_nac_name[LUAPI_MAX_OBJ_PATH_LEN];
- if (argc < 1) {
- return (1);
- }
- if (strlen(argv[0]) > MAX_ID_STR_LEN) {
- lprintf(LOG_ERR,
- "Sun OEM nacname command failed: Max size on IPMI name");
- return (-1);
- }
- nacname_req.seq_num = 0;
- strcpy(nacname_req.nac_name, argv[0]);
- full_nac_name[0] = '\0';
- while (1) {
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_SUNOEM;
- req.msg.cmd = IPMI_SUNOEM_NACNAME;
- req.msg.data = (uint8_t *) &nacname_req;
- req.msg.data_len = sizeof(sunoem_nacname_t);
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Sun OEM nacname command failed.");
- return (-1);
- }
- if (rsp->ccode != 0) {
- lprintf(LOG_ERR, "Sun OEM nacname command failed: %d", rsp->ccode);
- return (-1);
- }
- nacname_rsp = (sunoem_nacname_t *) rsp->data;
- strncat(full_nac_name, nacname_rsp->nac_name, MAX_SUNOEM_NAC_SIZE);
- /*
- * break out of the loop if there is no more data
- * In most cases, if not all, the NAC name fits into a
- * single payload
- */
- if (nacname_req.seq_num == nacname_rsp->seq_num) {
- break;
- }
- /* Get the next seq of string bytes */
- nacname_req.seq_num = nacname_rsp->seq_num;
- /* Check if we exceeded the size of the full nac name */
- if ((nacname_req.seq_num * MAX_SUNOEM_NAC_SIZE) > LUAPI_MAX_OBJ_PATH_LEN) {
- lprintf(LOG_ERR,
- "Sun OEM nacname command failed: invalid path length");
- return (-1);
- }
- }
- printf("NAC Name: %s\n", full_nac_name);
- return (0);
- }
- /* Constants used by ipmi_sunoem_getval */
- #define MAX_SUNOEM_VAL_PAYLOAD 79
- #define MAX_SUNOEM_VAL_COMPACT_PAYLOAD 56
- /*
- * SUNOEM GET/SET LUAPI Commands
- *
- * SUNOEM_REQ_VAL - Request LUAPI Property Value
- * SUNOEM_GET_VAL - Return the value from SUNOEM_REQ_VAL
- * SUNOEM_SET_VAL - Set the LUAPI Property value
- * SUNOEM_GET_STATUS - Return the Status from SUNOEM_SET_VAL
- */
- #define SUNOEM_REQ_VAL 1
- #define SUNOEM_GET_VAL 2
- #define SUNOEM_SET_VAL 3
- #define SUNOEM_GET_STATUS 4
- /* Status Code */
- #define SUNOEM_REQ_RECV 1
- #define SUNOEM_REQ_FAILED 2
- #define SUNOEM_DATA_READY 3
- #define SUNOEM_DATA_NOT_READY 4
- #define SUNOEM_DATA_NOT_FOUND 5
- #define GETVAL_MAX_RETRIES 5
- /* Parameter type Codes */
- #define SUNOEM_LUAPI_TARGET 0
- #define SUNOEM_LUAPI_VALUE 1
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(push, 1)
- #endif
- typedef struct
- {
- unsigned char cmd_code;
- unsigned char luapi_value[MAX_SUNOEM_VAL_PAYLOAD];
- }__attribute__((packed)) sunoem_getval_t;
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(pop)
- #endif
- /*
- * REQUEST PAYLOAD
- *
- * cmd_code - SUNOEM GET/SET LUAPI Cmds - see above
- * param_type: 0: luapi_data contains the luapi property name
- * 1: luapi_data contains the luapi value
- * luapi_data: Either luapi property name or value
- * tid: Transaction ID. If 0. This is the initial request for the
- * param_type. If tid > 0, this luapi_data string is a concatenation
- * of the previous request. Handle cases where the LUAPI target name
- * or value is > MAX_SUNOEM_VAL_COMPACT_PAYLOAD
- * eof: If non zero, this is the last payload for the request
- */
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(push, 1)
- #endif
- typedef struct
- {
- unsigned char cmd_code;
- unsigned char param_type;
- unsigned char tid;
- unsigned char eof;
- char luapi_data[MAX_SUNOEM_VAL_COMPACT_PAYLOAD];
- }__attribute__((packed)) sunoem_setval_t;
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(pop)
- #endif
- /*
- * RESPONSE PAYLOAD
- *
- * status_code - see above for code definitions
- * tid - transaction ID - assigned ny the ILOM stack
- */
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(push, 1)
- #endif
- typedef struct
- {
- unsigned char status_code;
- unsigned char tid;
- }__attribute__((packed)) sunoem_setval_resp_t;
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(pop)
- #endif
- /*
- * Return the ILOM target property value
- */
- static int
- ipmi_sunoem_getval(struct ipmi_intf * intf, int argc, char *argv[])
- {
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- sunoem_getval_t getval_req;
- sunoem_getval_t *getval_rsp;
- int i;
- const char* sp_path = "/SP";
- supported_version_t supp_ver = { 3, 2, 0, 0 };
- if (argc < 1) {
- return (1);
- }
- if (strlen(argv[0]) > MAX_SUNOEM_VAL_PAYLOAD) {
- lprintf(LOG_ERR,
- "Sun OEM get value command failed: Max size on IPMI name");
- return (-1);
- }
- if ((ipmi_sunoem_checkversion(intf, &supp_ver) < 0)
- && (!strncmp(argv[0], sp_path, strlen(sp_path)))) {
- argv[0][1] = 'X'; /*replace SP by X to gain access to hidden properties*/
- memmove(&argv[0][2], &argv[0][3], strlen(argv[0]) - 2);
- }
- /*
- * Setup the initial request to fetch the data.
- * Upon function return, the next cmd (SUNOEM_GET_VAL)
- * can be requested.
- */
- memset(&getval_req, 0, sizeof(getval_req));
- strncpy((char*) getval_req.luapi_value, argv[0], MAX_SUNOEM_VAL_PAYLOAD);
- getval_req.cmd_code = SUNOEM_REQ_VAL;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_SUNOEM;
- req.msg.cmd = IPMI_SUNOEM_GETVAL;
- req.msg.data = (uint8_t *) &getval_req;
- req.msg.data_len = sizeof(sunoem_getval_t);
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Sun OEM getval1 command failed.");
- return (-1);
- }
- if (rsp->ccode != 0) {
- lprintf(LOG_ERR, "Sun OEM getval1 command failed: %d", rsp->ccode);
- return (-1);
- }
- /*
- * Fetch the data value - if it is not ready,
- * retry the request up to GETVAL_MAX_RETRIES
- */
- for (i = 0; i < GETVAL_MAX_RETRIES; i++) {
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_SUNOEM;
- req.msg.cmd = IPMI_SUNOEM_GETVAL;
- getval_req.cmd_code = SUNOEM_GET_VAL;
- req.msg.data = (uint8_t *) &getval_req;
- req.msg.data_len = sizeof(sunoem_getval_t);
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Sun OEM getval2 command failed.");
- return (-1);
- }
- if (rsp->ccode != 0) {
- lprintf(LOG_ERR, "Sun OEM getval2 command failed: %d", rsp->ccode);
- return (-1);
- }
- getval_rsp = (sunoem_getval_t *) rsp->data;
- if (getval_rsp->cmd_code == SUNOEM_DATA_READY) {
- printf("Target Value: %s\n", getval_rsp->luapi_value);
- return (0);
- } else if (getval_rsp->cmd_code == SUNOEM_DATA_NOT_FOUND) {
- lprintf(LOG_ERR, "Target: %s not found", getval_req.luapi_value);
- return (-1);
- }
- sleep(1);
- }
- lprintf(LOG_ERR, "Unable to retrieve target value.");
- return (-1);
- }
- static int
- send_luapi_prop_name(struct ipmi_intf * intf, int len, char *prop_name,
- unsigned char *tid_num)
- {
- int i = 0;
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- sunoem_setval_t setval_req;
- sunoem_setval_resp_t *setval_rsp;
- *tid_num = 0;
- while (i < len) {
- /*
- * Setup the request,
- * Upon function return, the next cmd (SUNOEM_SET_VAL)
- * can be requested.
- */
- memset(&req, 0, sizeof(req));
- memset(&setval_req, 0, sizeof(sunoem_setval_t));
- req.msg.netfn = IPMI_NETFN_SUNOEM;
- req.msg.cmd = IPMI_SUNOEM_SETVAL;
- setval_req.cmd_code = SUNOEM_SET_VAL;
- setval_req.param_type = SUNOEM_LUAPI_TARGET;
- setval_req.tid = *tid_num;
- setval_req.eof = 0;
- /*
- * If the property name is > payload, only copy
- * the payload size and increment the string offset (i)
- * for the next payload
- */
- if (strlen(&(prop_name[i])) > MAX_SUNOEM_VAL_COMPACT_PAYLOAD) {
- strncpy(setval_req.luapi_data, &(prop_name[i]),
- MAX_SUNOEM_VAL_COMPACT_PAYLOAD);
- } else {
- strncpy(setval_req.luapi_data, &(prop_name[i]),
- strlen(&(prop_name[i])));
- }
- req.msg.data = (uint8_t *) &setval_req;
- req.msg.data_len = sizeof(sunoem_setval_t);
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Sun OEM setval prop name: response is NULL");
- return (-1);
- }
- if (rsp->ccode != 0) {
- lprintf(LOG_ERR, "Sun OEM setval prop name: request failed: %d",
- rsp->ccode);
- return (-1);
- }
- setval_rsp = (sunoem_setval_resp_t *) rsp->data;
- /*
- * If the return code is other than data received, the
- * request failed
- */
- if (setval_rsp->status_code != SUNOEM_REQ_RECV) {
- lprintf(LOG_ERR,
- "Sun OEM setval prop name: invalid status code: %d",
- setval_rsp->status_code);
- return (-1);
- }
- /* Use the tid returned by ILOM */
- *tid_num = setval_rsp->tid;
- /* Increment the string offset */
- i += MAX_SUNOEM_VAL_COMPACT_PAYLOAD;
- }
- return (0);
- }
- static int
- send_luapi_prop_value(struct ipmi_intf * intf, int len, char *prop_value,
- unsigned char tid_num)
- {
- int i = 0;
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- sunoem_setval_t setval_req;
- sunoem_setval_resp_t *setval_rsp;
- while (i < len) {
- /*
- * Setup the request,
- * Upon function return, the next cmd (SUNOEM_GET_VAL)
- * can be requested.
- */
- memset(&req, 0, sizeof(req));
- memset(&setval_req, 0, sizeof(sunoem_setval_t));
- req.msg.netfn = IPMI_NETFN_SUNOEM;
- req.msg.cmd = IPMI_SUNOEM_SETVAL;
- setval_req.cmd_code = SUNOEM_SET_VAL;
- setval_req.param_type = SUNOEM_LUAPI_VALUE;
- setval_req.tid = tid_num;
- /*
- * If the property name is > payload, only copy the
- * the payload size and increment the string offset
- * for the next payload
- */
- if (strlen(&(prop_value[i])) > MAX_SUNOEM_VAL_COMPACT_PAYLOAD) {
- strncpy(setval_req.luapi_data, &(prop_value[i]),
- MAX_SUNOEM_VAL_COMPACT_PAYLOAD);
- } else {
- /* Captured the entire string, mark this as the last payload */
- strncpy(setval_req.luapi_data, &(prop_value[i]),
- strlen(&(prop_value[i])));
- setval_req.eof = 1;
- }
- req.msg.data = (uint8_t *) &setval_req;
- req.msg.data_len = sizeof(sunoem_setval_t);
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Sun OEM setval prop value: response is NULL");
- return (-1);
- }
- if (rsp->ccode != 0) {
- lprintf(LOG_ERR, "Sun OEM setval prop value: request failed: %d",
- rsp->ccode);
- return (-1);
- }
- setval_rsp = (sunoem_setval_resp_t *) rsp->data;
- /*
- * If the return code is other than data received, the
- * request failed
- */
- if (setval_rsp->status_code != SUNOEM_REQ_RECV) {
- lprintf(LOG_ERR,
- "Sun OEM setval prop value: invalid status code: %d",
- setval_rsp->status_code);
- return (-1);
- }
- /* Increment the string offset */
- i += MAX_SUNOEM_VAL_COMPACT_PAYLOAD;
- }
- return (0);
- }
- static int
- ipmi_sunoem_setval(struct ipmi_intf * intf, int argc, char *argv[])
- {
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- sunoem_setval_t setval_req;
- sunoem_setval_resp_t *setval_rsp;
- int prop_len;
- int value_len;
- int i;
- unsigned char tid_num;
- int retries;
- prop_len = strlen(argv[0]);
- value_len = strlen(argv[1]);
- if (prop_len > LUAPI_MAX_OBJ_PATH_LEN) {
- lprintf(LOG_ERR,
- "Sun OEM set value command failed: Max size on property name");
- return (-1);
- }
- if (value_len > LUAPI_MAX_OBJ_VAL_LEN) {
- lprintf(LOG_ERR,
- "Sun OEM set value command failed: Max size on property value");
- return (-1);
- }
- /* Test if there is a timeout specified */
- if (argc == 3) {
- if ((str2int(argv[2], &retries) != 0) || retries < 0) {
- lprintf(LOG_ERR,
- "Invalid input given or out of range for time-out parameter.");
- return (-1);
- }
- } else {
- retries = GETVAL_MAX_RETRIES;
- }
- /* Send the property name 1st */
- if (send_luapi_prop_name(intf, prop_len, argv[0], &tid_num) != 0) {
- /* return if there is an error */
- return (-1);
- }
- if (send_luapi_prop_value(intf, value_len, argv[1], tid_num) != 0) {
- /* return if there is an error */
- return (-1);
- }
- /*
- * Get The status of the command.
- * if it is not ready, retry the request up to
- * GETVAL_MAX_RETRIES
- */
- for (i = 0; i < retries; i++) {
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_SUNOEM;
- req.msg.cmd = IPMI_SUNOEM_SETVAL;
- setval_req.cmd_code = SUNOEM_GET_STATUS;
- setval_req.tid = tid_num;
- req.msg.data = (uint8_t *) &setval_req;
- req.msg.data_len = sizeof(sunoem_setval_t);
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Sun OEM setval command failed.");
- return (-1);
- }
- if (rsp->ccode != 0) {
- lprintf(LOG_ERR, "Sun OEM setval command failed: %d", rsp->ccode);
- return (-1);
- }
- setval_rsp = (sunoem_setval_resp_t *) rsp->data;
- if (setval_rsp->status_code == SUNOEM_DATA_READY) {
- printf("Sun OEM setval command successful.\n");
- return (0);
- } else if (setval_rsp->status_code != SUNOEM_DATA_NOT_READY) {
- lprintf(LOG_ERR, "Sun OEM setval command failed.");
- return (-1);
- }
- sleep(1);
- }
- /* If we reached here, retries exceeded */
- lprintf(LOG_ERR, "Sun OEM setval command failed: Command Timed Out");
- return (-1);
- }
- #define MAX_FILE_DATA_SIZE 1024
- #define MAX_FILEID_LEN 16
- #define CORE_TUNNEL_SUBCMD_GET_FILE 11
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(push, 1)
- #endif
- typedef struct
- {
- unsigned char cmd_code;
- unsigned char file_id[MAX_FILEID_LEN];
- unsigned int block_num;
- }__attribute__((packed)) getfile_req_t;
- typedef struct
- {
- unsigned int block_num;
- unsigned int data_size;
- unsigned char eof;
- unsigned char data[MAX_FILE_DATA_SIZE];
- }__attribute__((packed)) getfile_rsp_t;
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(pop)
- #endif
- static int
- ipmi_sunoem_getfile(struct ipmi_intf * intf, int argc, char *argv[])
- {
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- getfile_req_t getfile_req;
- getfile_rsp_t *getfile_rsp;
- int block_num = 0;
- int nbo_blk_num; /* Network Byte Order Block Num */
- FILE *fp;
- unsigned data_size;
- supported_version_t supp_ver = IPMI_SUNOEM_GETFILE_VERSION;
- if (argc < 1) {
- return (-1);
- }
- /*check if command is supported by this version of ilom*/
- if (ipmi_sunoem_checkversion(intf, &supp_ver) < 0) {
- ipmi_sunoem_print_required_version(&supp_ver);
- return (-1);
- }
- /*
- * File ID is < MAX_FILEID_LEN
- * Save 1 byte for null Terminated string
- */
- if (strlen(argv[0]) >= MAX_FILE_DATA_SIZE) {
- lprintf(LOG_ERR, "File ID >= %d characters", MAX_FILEID_LEN);
- return (-1);
- }
- memset(&getfile_req, 0, sizeof(getfile_req));
- strncpy((char*) getfile_req.file_id, argv[0], MAX_FILEID_LEN - 1);
- /* Create the destination file */
- fp = ipmi_open_file_write(argv[1]);
- if (fp == NULL) {
- lprintf(LOG_ERR, "Unable to open file: %s", argv[1]);
- return (-1);
- }
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_SUNOEM;
- req.msg.cmd = IPMI_SUNOEM_CORE_TUNNEL;
- req.msg.data = (uint8_t *) &getfile_req;
- req.msg.data_len = sizeof(getfile_req_t);
- getfile_req.cmd_code = CORE_TUNNEL_SUBCMD_GET_FILE;
- do {
- nbo_blk_num = htonl(block_num);
- /* Block Num must be in network byte order */
- memcpy(&(getfile_req.block_num), &nbo_blk_num,
- sizeof(getfile_req.block_num));
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Sun OEM getfile command failed.");
- fclose(fp);
- return (-1);
- }
- if (rsp->ccode != 0) {
- lprintf(LOG_ERR, "Sun OEM getfile command failed: %d", rsp->ccode);
- fclose(fp);
- return (-1);
- }
- getfile_rsp = (getfile_rsp_t *) rsp->data;
- memcpy(&data_size, &(getfile_rsp->data_size),
- sizeof(getfile_rsp->data_size));
- data_size = ntohl(data_size);
- if (data_size > MAX_FILE_DATA_SIZE) {
- lprintf(LOG_ERR, "Sun OEM getfile invalid data size: %d",
- data_size);
- fclose(fp);
- return (-1);
- }
- /* Check if Block Num matches */
- if (memcmp(&(getfile_req.block_num), &(getfile_rsp->block_num),
- sizeof(getfile_req.block_num)) != 0) {
- lprintf(LOG_ERR, "Sun OEM getfile Incorrect Block Num Returned");
- lprintf(LOG_ERR, "Expecting: %x Received: %x",
- getfile_req.block_num, getfile_rsp->block_num);
- fclose(fp);
- return (-1);
- }
- if (fwrite(getfile_rsp->data, 1, data_size, fp) != data_size) {
- lprintf(LOG_ERR, "Sun OEM getfile write failed: %d", rsp->ccode);
- fclose(fp);
- return (-1);
- }
- block_num++;
- } while (getfile_rsp->eof == 0);
- fclose(fp);
- return (0);
- }
- /*
- * Query BMC for capability/behavior.
- */
- #define CORE_TUNNEL_SUBCMD_GET_BEHAVIOR 15
- #define SUNOEM_BEHAVIORID_SIZE 32
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(push, 1)
- #endif
- typedef struct
- {
- unsigned char cmd_code;
- unsigned char behavior_id[SUNOEM_BEHAVIORID_SIZE];
- }__attribute__((packed)) getbehavior_req_t;
- typedef struct
- {
- unsigned char enabled;
- }__attribute__((packed)) getbehavior_rsp_t;
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(pop)
- #endif
- static int
- ipmi_sunoem_getbehavior(struct ipmi_intf * intf, int argc, char *argv[])
- {
- struct ipmi_rq req;
- struct ipmi_rs *rsp;
- getbehavior_req_t getbehavior_req;
- getbehavior_rsp_t *getbehavior_rsp;
- supported_version_t supp_ver = IPMI_SUNOEM_GETBEHAVIOR_VERSION;
- if (argc < 1) {
- return (-1);
- }
- /*check if command is supported by this version of ilom*/
- if (ipmi_sunoem_checkversion(intf, &supp_ver) < 0) {
- ipmi_sunoem_print_required_version(&supp_ver);
- return (-1);
- }
- /*
- * Behavior ID is < SUNOEM_BEHAVIORID_SIZE.
- * Save 1 byte for null terminated string
- */
- if (strlen(argv[0]) >= SUNOEM_BEHAVIORID_SIZE) {
- lprintf(LOG_ERR, "Behavior ID >= %d characters",
- SUNOEM_BEHAVIORID_SIZE);
- return (-1);
- }
- memset(&getbehavior_req, 0, sizeof(getbehavior_req));
- strncpy(getbehavior_req.behavior_id, argv[0], SUNOEM_BEHAVIORID_SIZE - 1);
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_SUNOEM;
- req.msg.cmd = IPMI_SUNOEM_CORE_TUNNEL;
- req.msg.data = (uint8_t *) &getbehavior_req;
- req.msg.data_len = sizeof(getbehavior_req_t);
- getbehavior_req.cmd_code = CORE_TUNNEL_SUBCMD_GET_BEHAVIOR;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Sun OEM getbehavior command failed.");
- return (-1);
- }
- if (rsp->ccode != 0) {
- lprintf(LOG_ERR, "Sun OEM getbehavior command failed: %d", rsp->ccode);
- return (-1);
- }
- getbehavior_rsp = (getbehavior_rsp_t *) rsp->data;
- printf("ILOM behavior %s %s enabled\n", getbehavior_req.behavior_id,
- getbehavior_rsp->enabled ? "is" : "is not");
- return (0);
- }
- int
- ipmi_sunoem_main(struct ipmi_intf * intf, int argc, char ** argv)
- {
- int rc = 0;
- if (argc == 0 || strcmp(argv[0], "help") == 0) {
- ipmi_sunoem_usage();
- return (0);
- } /* if (argc == 0 || strcmp(argv[0], "help") == 0) */
- if (strcmp(argv[0], "cli") == 0) {
- rc = ipmi_sunoem_cli(intf, argc - 1, &argv[1]);
- } else if ((strcmp(argv[0], "led") == 0) || (strcmp(argv[0], "sbled") == 0)) {
- if (argc < 2) {
- ipmi_sunoem_usage();
- return (-1);
- }
- if (strcmp(argv[1], "get") == 0) {
- if (argc < 3) {
- char * arg[] = { "all" };
- rc = ipmi_sunoem_led_get(intf, 1, arg);
- } else {
- rc = ipmi_sunoem_led_get(intf, argc - 2, &(argv[2]));
- }
- } else if (strcmp(argv[1], "set") == 0) {
- if (argc < 4) {
- ipmi_sunoem_usage();
- return (-1);
- }
- rc = ipmi_sunoem_led_set(intf, argc - 2, &(argv[2]));
- } else {
- ipmi_sunoem_usage();
- return (-1);
- }
- } else if (strcmp(argv[0], "sshkey") == 0) {
- uint8_t uid = 0;
- if (argc < 3) {
- ipmi_sunoem_usage();
- return (-1);
- }
- rc = str2uchar(argv[2], &uid);
- if (rc == 0) {
- /* conversion should be OK. */
- } else if (rc == 2) {
- lprintf(LOG_NOTICE, "Invalid interval given.");
- return (-1);
- } else {
- /* defaults to rc = 3 */
- lprintf(LOG_NOTICE, "Given interval is too big.");
- return (-1);
- }
- if (strcmp(argv[1], "del") == 0) {
- /* number of arguments, three, is already checked at this point */
- rc = ipmi_sunoem_sshkey_del(intf, uid);
- } else if (strcmp(argv[1], "set") == 0) {
- if (argc < 4) {
- ipmi_sunoem_usage();
- return (-1);
- }
- rc = ipmi_sunoem_sshkey_set(intf, uid, argv[3]);
- } else {
- ipmi_sunoem_usage();
- return (-1);
- }
- } else if (strcmp(argv[0], "ping") == 0) {
- if (argc < 2) {
- ipmi_sunoem_usage();
- return (-1);
- }
- rc = ipmi_sunoem_echo(intf, argc - 1, &(argv[1]));
- } else if (strcmp(argv[0], "version") == 0) {
- rc = ipmi_sunoem_version(intf);
- } else if (strcmp(argv[0], "nacname") == 0) {
- if (argc < 2) {
- ipmi_sunoem_usage();
- return (-1);
- }
- rc = ipmi_sunoem_nacname(intf, argc - 1, &(argv[1]));
- } else if (strcmp(argv[0], "getval") == 0) {
- if (argc < 2) {
- ipmi_sunoem_usage();
- return (-1);
- }
- rc = ipmi_sunoem_getval(intf, argc - 1, &(argv[1]));
- } else if (strcmp(argv[0], "setval") == 0) {
- if (argc < 3) {
- ipmi_sunoem_usage();
- return (-1);
- }
- rc = ipmi_sunoem_setval(intf, argc - 1, &(argv[1]));
- } else if (strcmp(argv[0], "getfile") == 0) {
- if (argc < 3) {
- ipmi_sunoem_usage();
- return (-1);
- }
- rc = ipmi_sunoem_getfile(intf, argc - 1, &(argv[1]));
- } else if (strcmp(argv[0], "getbehavior") == 0) {
- if (argc < 2) {
- ipmi_sunoem_usage();
- return (-1);
- }
- rc = ipmi_sunoem_getbehavior(intf, argc - 1, &(argv[1]));
- } else {
- lprintf(LOG_ERR, "Invalid sunoem command: %s", argv[0]);
- return (-1);
- } /* if (strcmp(argv[0], "cli") == 0) */
- return (rc);
- }
|