summaryrefslogtreecommitdiff
path: root/util/iconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/iconfig.c')
-rw-r--r--util/iconfig.c2680
1 files changed, 2680 insertions, 0 deletions
diff --git a/util/iconfig.c b/util/iconfig.c
new file mode 100644
index 0000000..0bb54e9
--- /dev/null
+++ b/util/iconfig.c
@@ -0,0 +1,2680 @@
+/*---------------------------------------------------------------------------
+ * Filename: iconfig.c (was bmcconfig.c)
+ *
+ * Author: arcress at users.sourceforge.net
+ * Copyright (c) 2009 Kontron America, Inc.
+ *
+ * Abstract:
+ * This tool saves and restores the BMC Configuration parameters.
+ * This includes BMC PEF, LAN, Serial, User, Channel, and SOL parameters.
+ *
+ * ----------- Change History -----------------------------------------------
+ * 08/18/08 Andy Cress - created from pefconfig.c
+ */
+/*M*
+ *---------------------------------------------------------------------------
+Copyright (c) 2009 Kontron America, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ a.. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ b.. Redistributions 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.
+ c.. Neither the name of Kontron nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *---------------------------------------------------------------------------
+ *M*/
+#ifdef WIN32
+#include <winsock2.h>
+#include <iphlpapi.h>
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "getopt.h"
+#elif defined(DOS)
+#include <dos.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#if defined(HPUX)
+/* getopt is defined in stdio.h */
+#elif defined(MACOS)
+/* getopt is defined in unistd.h */
+#include <unistd.h>
+#else
+#include <getopt.h>
+#endif
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <errno.h>
+#endif
+#ifdef SOLARIS
+#include <sys/sockio.h>
+#define SIOCGIFHWADDR SIOCGENADDR
+#define ifr_netmask ifr_ifru.ifru_addr
+#elif defined(BSD)
+#include <sys/sockio.h>
+#define SIOCGIFHWADDR SIOCGIFMAC
+#define ifr_netmask ifr_ifru.ifru_addr
+#elif defined(MACOS)
+#include <sys/sockio.h>
+// #define SIOCGIFHWADDR SIOCGIFMAC
+#define ifr_netmask ifr_ifru.ifru_addr
+#endif
+#include "ipmicmd.h"
+#include "oem_intel.h"
+
+extern int find_ifname(char *ifname); /*see idiscover.c*/
+/* atoip was moved to subs.c, defined in ipmicmd.h */
+
+#define SELprintf printf
+#define RTF_UP 0x0001 /* route usable */
+
+#define SOL_ENABLE_FLAG 0x01
+#define SOL_DISABLE_FLAG 0x00
+#define SOL_PRIVILEGE_LEVEL_USER 0x02
+#define SOL_PREFERRED_BAUD_RATE 0x07 /*19.2k*/
+/* For IPMI 1.5, use Intel SOL commands & subfunctions */
+#define SOL_ENABLE_PARAM 0x01
+#define SOL_AUTHENTICATION_PARAM 0x02
+#define SOL_ACC_INTERVAL_PARAM 0x03
+#define SOL_RETRY_PARAM 0x04
+#define SOL_BAUD_RATE_PARAM 0x05 /*non-volatile*/
+#define SOL_VOL_BAUD_RATE_PARAM 0x06 /*volatile*/
+/* For IPMI 2.0, use IPMI SOL commands & subfunctions */
+#define SOL_ENABLE_PARAM2 0x08
+#define SOL_AUTHENTICATION_PARAM2 0x09
+#define SOL_BAUD_RATE_PARAM2 0x11
+
+/* IPMI 2.0 SOL PAYLOAD commands */
+#define SET_PAYLOAD_ACCESS 0x4C
+#define GET_PAYLOAD_ACCESS 0x4D
+#define GET_PAYLOAD_SUPPORT 0x4E
+
+/* Channel Access values */
+#define CHAN_ACC_DISABLE 0x20 /* PEF off, disabled*/
+#define CHAN_ACC_PEFON 0x02 /* PEF on, always avail */
+#define CHAN_ACC_PEFOFF 0x22 /* PEF off, always avail*/
+/* special channel access values for ia64 */
+#define CHAN_ACC_PEFON64 0x0A /* PEF on, always avail, UserLevelAuth=off */
+#define CHAN_ACC_PEFOFF64 0x2A /* PEF off, always avail, UserLevelAuth=off */
+
+ /* TSRLT2/TIGPR2U Channels: 0=IPMB, 1=Serial/EMP, 6=LAN2, 7=LAN1 */
+ /* S5000/other Channels: 1=LAN1, 2=LAN2, 3=LAN3, 4=Serial, 6=pci, 7=sys */
+#define LAN_CH 1
+#define SER_CH 4
+#define MAXCHAN 12 /*was 16, reduced for gnu ipmi_lan*/
+#define NUM_DEVICES_TO_CHECK 32 /*for GetBmcEthDevice()*/
+#define MAC_LEN 6 /*length of MAC Address*/
+#define PSW_LEN 16 /*see also PSW_MAX=20 in ipmicmd.h*/
+#define MAXPEF 41 /* max pefnum offset = 40 (41 entries) */
+
+ /* IP address source values */
+#define SRC_STATIC 0x01
+#define SRC_DHCP 0x02 /* BMC running DHCP */
+#define SRC_BIOS 0x03 /* BIOS, sometimes DHCP */
+#define SRC_OTHER 0x04
+
+/* PEF event severities */
+#define PEF_SEV_UNSPEC 0x00
+#define PEF_SEV_MON 0x01
+#define PEF_SEV_INFO 0x02
+#define PEF_SEV_OK 0x04
+#define PEF_SEV_WARN 0x08
+#define PEF_SEV_CRIT 0x10
+#define PEF_SEV_NORECOV 0x20
+
+typedef struct
+{ /* See IPMI Table 15-2 */
+ uchar rec_id;
+ uchar fconfig;
+ uchar action;
+ uchar policy;
+ uchar severity;
+ uchar genid1;
+ uchar genid2;
+ uchar sensor_type;
+ uchar sensor_no;
+ uchar event_trigger;
+ uchar data1;
+ uchar mask1;
+ uchar res[9];
+} PEF_RECORD;
+
+/*
+ * Global variables
+ */
+static char * progver = "2.93";
+static char * progname = "iconfig";
+static char fdebug = 0;
+static char fipmilan = 0;
+static FILE * fd_bmc = NULL;
+static char fIPMI10 = 0; /* =1 if IPMI v1.0 or less */
+static char fIPMI20 = 0; /* =1 if IPMI v2.0 or greater */
+static char fSOL20 = 1; /* =1 if SOL v2.0 is ok */
+static char freadonly = 1; /* =1 to only read LAN & PEF parameters */
+static char func = 'd'; /* function: display, save, restore */
+static char fdomac = 0; /* =1 to restore MAC also */
+static char fpassword = 0; /* =1 user-specified a password, so set it. */
+static uchar fmBMC = 0;
+static uchar fiBMC = 0;
+static uchar fRomley = 0;
+static char fipv6 = 0;
+static char fcanonical = 0;
+static char fchan2wart = 0; /* =1 if need wart to skip channel 2 */
+static char bdelim = BCOLON; /*':' as default*/
+static char bcomment = BCOMMENT; /* '#' */
+static char pefmax = MAXPEF; /* 20 for Sahalee, 30 for miniBMC */
+static int nerrs = 0;
+static int ngood = 0;
+static int lasterr = 0;
+static uchar nusers = 5;
+static uchar max_users = 5;
+static uchar enabled_users = 0;
+static uchar last_user_enable = 0; /* last user enabled */
+static uchar passwordData[16];
+static uchar fsetifn = 0;
+static ushort setsolcmd;
+static ushort getsolcmd;
+static uchar sol_bchan = 0;
+static uchar authmask = 0;
+static uchar lan_access = 0x04; /* see SetPassword*/
+
+static uchar pefnum = 12;
+static uchar fsharedMAC = 0;
+//static uchar alertnum = 1;
+//static uchar rgdestip[4];
+static uchar rgdestmac[6];
+static uchar rggwymac[6];
+#ifdef WIN32
+static uchar rggwyip[4] = {0,0,0,0};
+static uchar rgmyip [4] = {0,0,0,0}; /*WIN32*/
+static uchar rgmymac[6] = {0xFF,0,0,0,0,0}; /*WIN32*/
+static uchar rgsubnet[4] = {0,0,0,0}; /*WIN32*/
+static uchar osmyip[4] = {0,0,0,0};
+static uchar osmymac[6] = {0xff,0,0,0,0,0};
+#endif
+static uchar bmcmyip[4] = {0,0,0,0};
+static uchar bmcdestip[4] = {0,0,0,0};
+static uchar bmcmymac[6] = {0xFF,0,0,0,0,0};
+static char ifname[16] = "eth0"; /* interface name */
+static char ifname0[16] = "eth0"; /* first interface name */
+static char ifpattn[14] = "eth"; /* default, discovered via find_ifname */
+static int vend_id;
+static int prod_id;
+static uchar ser_ch = 0; /*was SER_CH==4*/
+static uchar lan_ch = LAN_CH;
+static uchar lan_ch_parm = 0xff;
+static uchar lan_ch_sav = 0xff;
+static uchar gcm_ch = 0;
+static uchar SessInfo[16];
+static uchar chan_type[MAXCHAN];
+static int nlans = 0;
+#define MAX_PEFPARAMS 14 /* max pef params = 14 */
+static char **pefdesc;
+static char *pefdesc1[MAXPEF] = { /* for Sahalee BMC */
+/* 0 0x00 */ "",
+/* 1 0x01 */ "Temperature Sensor",
+/* 2 0x02 */ "Voltage Sensor",
+/* 3 0x04 */ "Fan Failure",
+/* 4 0x05 */ "Chassis Intrusion",
+/* 5 0x08 */ "Power Supply Fault",
+/* 6 0x0c */ "Memory ECC Error",
+/* 7 0x0f */ "FRB Failure",
+/* 8 0x07 */ "BIOS POST Error",
+/* 9 0x13 */ "Fatal NMI",
+/*10 0x23 */ "Watchdog Timer Reset",
+/*11 0x12 */ "System Restart",
+/*12 0x20 */ "OS Critical Stop",
+/*13 0x09 */ "Power Redundancy Lost",
+/*14 0x00 */ "reserved",
+/*15 0x00 */ "reserved",
+/*16 0x00 */ "reserved",
+/*17 */ "reserved",
+/*18 */ "reserved",
+/*19 */ "reserved",
+/*20 */ "reserved",
+/*21 */ "reserved",
+/*22 */ "reserved",
+/*23 */ "reserved",
+/*24 */ "reserved",
+/*25 */ "reserved",
+/*26 */ "reserved",
+/*27 */ "reserved",
+/*28 */ "reserved",
+/*29 */ "unused",
+/*30 */ "unused" };
+
+static char *pefdesc2[MAXPEF] = { /* for NSC miniBMC */
+/* 0 */ "",
+/* 1 0x02*/ "Voltage Sensor Assert",
+/* 2 0x23*/ "Watchdog FRB Timeout", /* was "Proc FRB Thermal", */
+/* 3 0x02*/ "Voltage Sensor Deassert",
+/* 4 0x07*/ "Proc1 IERR",
+/* 5 0xff*/ "Digital Sensor OK",
+/* 6 0x14*/ "Chassis Identify",
+/* 7 0x13*/ "NMI Button",
+/* 8 0x14*/ "Clear CMOS via Panel",
+/* 9 0x0f*/ "OS Load POST Code",
+/*10 0x20*/ "OS Critical Stop",
+/*11 0x09 */ "Power Redundancy Lost",
+/*12 0x00*/ "reserved",
+/*13 */ "reserved",
+/*14 */ "reserved",
+/*15 */ "reserved",
+/*16 */ "reserved",
+/*17 */ "reserved",
+/*18 */ "reserved",
+/*19 */ "reserved",
+/*20 */ "reserved",
+/*21 */ "reserved",
+/*22 */ "reserved",
+/*23 */ "reserved",
+/*24 */ "reserved",
+/*25 */ "reserved",
+/*26 0x05*/ "Chassis Intrusion",
+/*27 0x0f*/ "POST Code Error",
+/*28 0x02*/ "Voltage Failure",
+/*29 0x04*/ "Fan Failure",
+/*30 0x01*/ "Temperature Failure"};
+
+#define NLAN 39
+static struct {
+ int cmd;
+ int sz;
+ char desc[28];
+} lanparams[NLAN] = { /* see IPMI Table 19-4 */
+ /* 0 */ { 0, 1, "Set in progress"},
+ /* 1 */ { 1, 1, "Auth type support"},
+ /* 2 */ { 2, 5, "Auth type enables"},
+ /* 3 */ { 3, 4, "IP address"},
+ /* 4 */ { 4, 1, "IP addr src"}, /* (DHCP/Static) */
+ /* 5 */ { 5, 6, "MAC addr"},
+ /* 6 */ { 6, 4, "Subnet mask"},
+ /* 7 */ { 7, 3, "IPv4 header"},
+ /* 8 */ { 8, 2, "Prim RMCP port"},
+ /* 9 */ { 9, 2, "Sec RMCP port"},
+ /* 10 */ {10, 1, "BMC grat ARP"},
+ /* 11 */ {11, 1, "grat ARP interval"},
+ /* 12 */ {12, 4, "Def gateway IP"},
+ /* 13 */ {13, 6, "Def gateway MAC"},
+ /* 14 */ {14, 4, "Sec gateway IP"},
+ /* 15 */ {15, 6, "Sec gateway MAC"},
+ /* 16 */ {16,18, "Community string"},
+ /* 17 */ {17, 1, "Num dest"},
+ /* 18 */ {18, 5, "Dest type"},
+ /* 19 */ {19, 13, "Dest address"},
+ /* 20 */ {20, 2, "VLAN ID"},
+ /* 21 */ {21, 1, "VLAN Priority"},
+ /* 22 */ {22, 1, "Cipher Suite Support"},
+ /* 23 */ {23,17, "Cipher Suites"},
+ /* 24 */ {24, 9, "Cipher Suite Privilege"},
+ /* 25 */ {25, 4, "VLAN Dest Tag"},
+ /* 26 */ {96, 28, "OEM Alert String"},
+ /* 27 */ {97, 1, "Alert Retry Algorithm"},
+ /* 28 */ {98, 3, "UTC Offset"},
+ /* 29 */ {102, 1, "IPv6 Enable"},
+ /* 30 */ {103, 1, "IPv6 Addr Source"},
+ /* 31 */ {104,16, "IPv6 Address"},
+ /* 32 */ {105, 1, "IPv6 Prefix Len"},
+ /* 33 */ {106,16, "IPv6 Default Gateway"},
+ /* 34 */ {108,17, "IPv6 Dest address"},
+ /* 35 */ {192, 4, "DHCP Server IP"},
+ /* 36 */ {193, 6, "DHCP MAC Address"},
+ /* 37 */ {194, 1, "DHCP Enable"},
+ /* 38 */ {201, 2, "Channel Access Mode(Lan)"}
+};
+
+#define NSER 22 /* max=32 */
+static struct {
+ int cmd;
+ int sz;
+ char desc[28];
+} serparams[NSER] = { /* see IPMI Table 20-4 */
+ /* 0 */ { 0, 1, "Set in progress"},
+ /* 1 */ { 1, 1, "Auth type support"},
+ /* 2 */ { 2, 5, "Auth type enables"},
+ /* 3 */ { 3, 1, "Connection Mode"},
+ /* 4 */ { 4, 1, "Sess Inactiv Timeout"},
+ /* 5 */ { 5, 5, "Channel Callback"},
+ /* 6 */ { 6, 1, "Session Termination"},
+ /* 7 */ { 7, 2, "IPMI Msg Comm"},
+ /* 8 */ { 8, 2, "Mux Switch"},
+ /* 9 */ { 9, 2, "Modem Ring Time"},
+ /* 10 */ {10,17, "Modem Init String"},
+ /* 11 */ {11, 5, "Modem Escape Seq"},
+ /* 12 */ {12, 8, "Modem Hangup Seq"},
+ /* 13 */ {13, 8, "Modem Dial Command"},
+ /* 14 */ {14, 1, "Page Blackout Interval"},
+ /* 15 */ {15,18, "Community String"},
+ /* 16 */ {16, 1, "Num of Alert Dest"},
+ /* 17 */ {17, 5, "Destination Info"},
+ /* 18 */ {18, 1, "Call Retry Interval"},
+ /* 19 */ {19, 3, "Destination Comm Settings"},
+ /* 20 */ {29, 2, "Terminal Mode Config"},
+ /* 21 */ {201, 2,"Channel Access Mode (Ser)"}
+};
+
+#define NSYS 6 /* num SystemParam */
+#define CHAS_RESTORE 0x00 /*chassis power restore policy*/
+#define SYS_INFO 0x01 /*System Info (1,2,3,4) */
+#define LAN_FAILOVER 0x02 /*Intel LAN Failover*/
+/* TODO: Future DCMI 1.5 params */
+#define DCMI_POWER 0x03 /*DCMI Power limit*/
+#define DCMI_THERMAL 0x04 /*DCMI Thermal params*/
+#define DCMI_CONFIG 0x05 /*DCMI Config params*/
+
+static int GetDeviceID(uchar *pLanRecord)
+{
+ uchar responseData[MAX_BUFFER_SIZE];
+ int responseLength = MAX_BUFFER_SIZE;
+ int status;
+ uchar inputData[24];
+ uchar completionCode;
+
+ if (pLanRecord == NULL) return(-1);
+
+ status = ipmi_cmd(GET_DEVICE_ID, inputData, 0, responseData,
+ &responseLength, &completionCode, fdebug);
+
+ if (status == ACCESS_OK) {
+ if( completionCode ) {
+ SELprintf("GetDeviceID: completion code=%x\n",
+ completionCode);
+ status = completionCode;
+ } else {
+ memcpy(pLanRecord,&responseData[0],responseLength);
+ set_mfgid(&responseData[0],responseLength);
+ return(0); // successful, done
+ }
+ } /* endif */
+ /* if get here, error */
+ return(status);
+} /*end GetDeviceID() */
+
+static int GetChanAcc(uchar chan, uchar parm, uchar *pLanRecord)
+{
+ uchar responseData[MAX_BUFFER_SIZE];
+ int responseLength = MAX_BUFFER_SIZE;
+ int status;
+ uchar inputData[24];
+ uchar completionCode;
+
+ if (pLanRecord == NULL) return(-1);
+ responseLength = 3;
+ inputData[0] = chan;
+ inputData[1] = parm; /* 0x80 = active, 0x40 = non-volatile */
+ responseLength = sizeof(responseData);
+ status = ipmi_cmd(GET_CHANNEL_ACC, inputData, 2, responseData,
+ &responseLength, &completionCode, fdebug);
+
+ if (status == ACCESS_OK) {
+ if( completionCode ) {
+ SELprintf("%c GetChanAcc: completion code=%x\n",
+ bcomment,completionCode);
+ status = completionCode;
+ } else {
+ // dont copy first byte (Parameter revision, usu 0x11)
+ memcpy(pLanRecord,&responseData[0],responseLength);
+ return(0); // successful, done
+ }
+ } /* endif */
+ /* if get here, error */
+ return(status);
+} /*GetChanAcc()*/
+
+static int SetChanAcc(uchar chan, uchar parm, uchar val, uchar access)
+{
+ uchar responseData[MAX_BUFFER_SIZE];
+ int responseLength = MAX_BUFFER_SIZE;
+ int status;
+ uchar inputData[24];
+ uchar completionCode;
+
+ if (fmBMC) return(0); /* mBMC doesn't support this */
+ /* parm: 0x80 = active, 0x40 = set non-vol*/
+ responseLength = 1;
+ inputData[0] = chan; /* channel */
+ inputData[1] = (parm & 0xc0) | (val & 0x3F);
+ inputData[2] = (parm & 0xc0) | access; /* set priv level */
+
+ responseLength = sizeof(responseData);
+ status = ipmi_cmd(SET_CHANNEL_ACC, inputData, 3, responseData,
+ &responseLength, &completionCode, fdebug);
+
+ if (status == ACCESS_OK) {
+ if( completionCode ) {
+ SELprintf("SetChanAcc: completion code=%x\n",
+ completionCode);
+ status = completionCode;
+ } else {
+ return(0); // successful, done
+ }
+ } /* endif */
+ /* if get here, error */
+ return(status);
+} /*SetChanAcc()*/
+
+static int GetUser(int user_num)
+{
+ uchar responseData[MAX_BUFFER_SIZE];
+ int responseLength = MAX_BUFFER_SIZE;
+ int status, i;
+ uchar completionCode;
+ char inputData[24];
+
+ inputData[0] = lan_ch;
+ inputData[1] = (uchar)user_num; /* usually = 1 for BMC LAN */
+ responseLength = sizeof(responseData);
+ status = ipmi_cmd(GET_USER_ACCESS, inputData, 2, responseData,
+ &responseLength, &completionCode, fdebug);
+ if (status == 0 && completionCode == 0) {
+ uchar c;
+ if (user_num == 1) {
+ max_users = responseData[0] & 0x3f;
+ enabled_users = responseData[1] & 0x3f;
+ if (enabled_users > nusers) nusers = enabled_users;
+ }
+ fprintf(fd_bmc,"UserAccess %d,%d%c %02x %02x %02x %02x \n",
+ lan_ch,user_num,bdelim,responseData[0],responseData[1],
+ responseData[2], responseData[3]);
+ c = responseData[3];
+ inputData[0] = (uchar)user_num; /* usually = 1 for BMC LAN */
+ responseLength = sizeof(responseData);
+ status = ipmi_cmd(GET_USER_NAME, inputData, 1, responseData,
+ &responseLength, &completionCode, fdebug);
+ if (status != 0 || completionCode != 0)
+ responseData[0] = 0;
+ else {
+ fprintf(fd_bmc,"UserName %d%c",user_num,bdelim);
+ for (i=0; i< responseLength; i++)
+ fprintf(fd_bmc," %02x",responseData[i]);
+ fprintf(fd_bmc,"\n");
+ fprintf(fd_bmc,"%c UserPassword %d%c",bcomment,user_num,bdelim);
+ for (i=0; i< PSW_LEN; i++)
+ fprintf(fd_bmc," 00");
+ fprintf(fd_bmc,"\n");
+ }
+ } else
+ printf("%c GetUserAccess(%d,%d), status=%x, ccode=%x\n",
+ bcomment,lan_ch,user_num, status, completionCode);
+ return(status);
+} /*end GetUser()*/
+
+static int GetSerEntry(uchar subfunc, uchar bset, uchar *pLanRecord)
+{
+ uchar responseData[MAX_BUFFER_SIZE];
+ int responseLength = MAX_BUFFER_SIZE;
+ uchar inputData[24];
+ int status;
+ uchar completionCode;
+ uchar chan;
+
+ if (pLanRecord == NULL)
+ {
+ if (fdebug)
+ printf("GetSerEntry(%d): error, output buffer is NULL\n",subfunc);
+ return (-1);
+ }
+
+ chan = ser_ch; /* 1=EMP, 0=IPMB, 6=LAN2, 7=LAN1 */
+
+ inputData[0] = chan; // flags, channel 3:0 (1=EMP)
+ inputData[1] = subfunc; // Param selector
+ inputData[2] = bset; // Set selector
+ inputData[3] = 0; // Block selector
+ if (subfunc == 10) {
+ inputData[2] = 0;
+ inputData[3] = 1;
+ }
+
+ status = ipmi_cmd(GET_SER_CONFIG, inputData, 4, responseData,
+ &responseLength, &completionCode, fdebug);
+ if (status == ACCESS_OK) {
+ if( completionCode ) {
+ if (fdebug)
+ SELprintf("GetSerEntry(%d,%d): completion code=%x\n",
+ chan,subfunc,completionCode);
+ status = completionCode;
+ } else {
+ // dont copy first byte (Parameter revision, usu 0x11)
+ memcpy(pLanRecord,&responseData[1],responseLength-1);
+ pLanRecord[responseLength-1] = 0;
+ //successful, done
+ return(0);
+ }
+ }
+
+ // we are here because completionCode is not COMPLETION_CODE_OK
+ if (fdebug)
+ SELprintf("GetSerEntry(%d,%d): ipmi_cmd status=%x ccode=%x\n",
+ chan,subfunc,status,completionCode);
+ return status;
+}
+
+static int SetSerEntry(uchar subfunc, uchar *pSerRecord, int reqlen)
+{
+ uchar responseData[MAX_BUFFER_SIZE];
+ int responseLength = MAX_BUFFER_SIZE;
+ uchar inputData[24];
+ int status;
+ uchar completionCode;
+
+ if (pSerRecord == NULL) {
+ if (fdebug)
+ printf("SetSerEntry(%d): error, input buffer is NULL\n",
+ subfunc);
+ return (-1);
+ }
+ inputData[0] = ser_ch; // flags, channel 3:0 (EMP)
+ inputData[1] = subfunc; // Param selector
+ memcpy(&inputData[2],pSerRecord,reqlen);
+ status = ipmi_cmd(SET_SER_CONFIG, inputData, (uchar)(reqlen+2),
+ responseData, &responseLength, &completionCode, fdebug);
+
+ if (fdebug)
+ printf("SetSerEntry: ipmi_cmd status=%d, completion code=%d\n",
+ status,completionCode);
+ if (status == ACCESS_OK) {
+ if( completionCode ) {
+ status = completionCode;
+ if (completionCode == 0x80)
+ printf("SetSerEntry(%d): Parameter not supported\n",
+ subfunc);
+ else
+ printf("SetSerEntry(%d): completion code=%x\n",
+ subfunc, completionCode);
+ }
+ // else successful, done
+ }
+ return status;
+} /* end SetSerEntry() */
+
+static int GetLanEntry(uchar subfunc, uchar bset, uchar *pLanRecord)
+{
+ uchar responseData[MAX_BUFFER_SIZE];
+ int responseLength = MAX_BUFFER_SIZE;
+ uchar inputData[24];
+ int status, n;
+ uchar completionCode;
+ uchar chan;
+
+ if (pLanRecord == NULL) {
+ if (fdebug) printf("GetLanEntry: error, output buffer is NULL\n");
+ return (-1);
+ }
+
+ chan = lan_ch; /* LAN 1 = 7 */
+
+ inputData[0] = chan; // flags, channel 3:0 (LAN 1)
+ inputData[1] = subfunc; // Param selector (3 = ip addr)
+ inputData[2] = bset; // Set selector
+ inputData[3] = 0; // Block selector
+
+ status = ipmi_cmd(GET_LAN_CONFIG, inputData, 4, responseData,
+ &responseLength, &completionCode, fdebug);
+
+ if (status == ACCESS_OK) {
+ if( completionCode ) {
+ if (fdebug)
+ SELprintf("GetLanEntry(%d,%d): completion code=%x\n",
+ chan,subfunc,completionCode);
+ status = completionCode;
+ } else {
+ // dont copy first byte (Parameter revision, usu 0x11)
+ if (responseLength > 0) {
+ n = responseLength-1;
+ memcpy(pLanRecord,&responseData[1],n);
+ } else n = 0;
+ pLanRecord[n] = 0;
+ //successful, done
+ return(0);
+ }
+ }
+
+ // we are here because completionCode is not COMPLETION_CODE_OK
+ if (fdebug)
+ SELprintf("GetLanEntry(%d,%d): status=%d completionCode=%x\n",
+ chan,subfunc,status,completionCode);
+ return (status);
+} /* end GetLanEntry() */
+
+static int SetLanEntry(uchar subfunc, uchar *pLanRecord, int reqlen)
+{
+ uchar responseData[MAX_BUFFER_SIZE];
+ int responseLength = MAX_BUFFER_SIZE;
+ uchar inputData[24];
+ int status;
+ uchar completionCode;
+
+ if (pLanRecord == NULL)
+ {
+ if (fdebug)
+ printf("SetLanEntry(%d): error, input buffer is NULL\n",subfunc);
+ return (-1);
+ }
+
+ if ((vend_id == VENDOR_SUPERMICROX) ||
+ (vend_id == VENDOR_SUPERMICRO)) {
+ /* SUPERMICRO cannot set grat arp or grat arp interval */
+ if (subfunc == 10 || subfunc == 11) return(0);
+ }
+ inputData[0] = lan_ch; // flags, channel 3:0 (LAN 1)
+ inputData[1] = subfunc; // Param selector (3 = ip addr)
+ memcpy(&inputData[2],pLanRecord,reqlen);
+
+ status = ipmi_cmd(SET_LAN_CONFIG, inputData, (uchar)(reqlen+2),
+ responseData, &responseLength,&completionCode,fdebug);
+
+ if (status == ACCESS_OK) {
+ if( completionCode ) {
+ if (fdebug)
+ SELprintf("SetLanEntry(%d,%d): completion code=%x\n",
+ lan_ch,subfunc,completionCode);
+ return(completionCode);
+ } else {
+ //successful, done
+ return(0);
+ }
+ }
+
+ // we are here because completionCode is not COMPLETION_CODE_OK
+ if (fdebug)
+ SELprintf("SetLanEntry(%d,%d): ipmi_cmd status=%d ccode=%x\n",
+ lan_ch,subfunc,status,completionCode);
+ return (status);
+} /* end SetLanEntry() */
+
+static int GetPefEntry(uchar subfunc, ushort rec_id, PEF_RECORD *pPefRecord)
+{
+ uchar responseData[MAX_BUFFER_SIZE];
+ int responseLength = MAX_BUFFER_SIZE;
+ uchar inputData[24];
+ int status, n;
+ uchar completionCode;
+
+ if (pPefRecord == NULL)
+ {
+ if (fdebug)
+ printf("GetPefEntry(%d): error, output buffer is NULL\n",subfunc);
+ return (-1);
+ }
+
+ inputData[0] = subfunc; // Parameter = Evt Filter Table
+ inputData[1] = (uchar)rec_id;
+ inputData[2] = 0;
+
+ status = ipmi_cmd(GET_PEF_CONFIG, inputData, 3, responseData,
+ &responseLength, &completionCode, fdebug);
+
+ if (status == ACCESS_OK) {
+ if( completionCode ) {
+ if (fdebug)
+ SELprintf("GetPefEntry(%d/%d): completion code=%x\n",
+ subfunc,rec_id,completionCode);
+ status = completionCode;
+ } else {
+ /* expect PEF record to be >=21 bytes */
+ if (responseLength > 1) n = responseLength-1;
+ else n = 0;
+ if (n > 21) n = 21;
+ // dont copy first byte (Parameter revision, usu 0x11)
+ if (n == 0) memset(pPefRecord,0,21);
+ else memcpy(pPefRecord,&responseData[1],n);
+ //successful, done
+ return(0);
+ }
+ }
+
+ // we are here because completionCode is not COMPLETION_CODE_OK
+ if (fdebug)
+ SELprintf("GetPefEntry: ipmi_cmd status=%x completionCode=%x\n",
+ status, completionCode);
+ return status;
+} /* end GetPefEntry() */
+
+static int SetPefEntry(PEF_RECORD *pPefRecord)
+{
+ uchar responseData[MAX_BUFFER_SIZE];
+ int responseLength = MAX_BUFFER_SIZE;
+ uchar inputData[24]; /* sizeof(PEF_RECORD) = 21 +1=22 */
+ int status;
+ uchar completionCode;
+ uchar subfunc;
+
+ subfunc = 0x06; // Parameter = Evt Filter Table
+
+ if (pPefRecord == NULL) {
+ if (fdebug)
+ printf("SetPefEntry: error, output buffer is NULL\n");
+ return (-1);
+ }
+
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
+ // 06 0c 80 01 01 00 ff ff 20 ff 6f ff 00 00 00 00 00 00 00 00 00 00
+ // memset(&inputData[0],0,requestData.dataLength);
+ inputData[0] = subfunc;
+ memcpy(&inputData[1],pPefRecord,sizeof(PEF_RECORD));
+
+ status = ipmi_cmd(SET_PEF_CONFIG, inputData, sizeof(PEF_RECORD)+1,
+ responseData, &responseLength, &completionCode, fdebug);
+
+ if (status == ACCESS_OK) {
+ if( completionCode ) {
+ if (fdebug)
+ SELprintf("SetPefEntry: completion code=%x\n",
+ completionCode); // responseData[0]);
+ status = completionCode;
+ } else {
+ //successful, done
+ return(0);
+ }
+
+ }
+
+ // we are here because completionCode is not COMPLETION_CODE_OK
+ if (fdebug)
+ SELprintf("SetPefEntry: ipmi_cmd status=%d ccode=%x\n",
+ status,completionCode);
+ return(status);
+
+} /* end SetPefEntry() */
+
+static int MacIsValid(uchar *mac)
+{
+ int fvalid = 0;
+ int i;
+ /* check for initial invalid value of FF:00:... */
+ if (mac[0] == 0xFF && mac[1] == 0x00) /* marked as invalid */
+ return(fvalid);
+ /* check for all zeros */
+ for (i = 0; i < MAC_LEN; i++)
+ if (mac[i] != 0) { /* not all zeros */
+ fvalid = 1;
+ break;
+ }
+ return(fvalid);
+}
+
+static int IpIsValid(uchar *ipadr)
+{
+ int fvalid = 1;
+ if (ipadr[0] == 0) fvalid = 0;
+ return(fvalid);
+}
+
+static int SubnetIsValid(uchar *subnet)
+{
+ int fvalid = 0;
+ /* if masking off at least one bit, say valid */
+ if ((subnet[0] & 0x80) == 0x80) fvalid = 1;
+ return(fvalid);
+}
+
+#ifdef WIN32
+/*
+ * Obtain network adapter information (Windows).
+ */
+static PIP_ADAPTER_ADDRESSES GetAdapters() {
+ PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL;
+ ULONG OutBufferLength = 0;
+ ULONG RetVal = 0, i;
+
+ // The size of the buffer can be different
+ // between consecutive API calls.
+ // In most cases, i < 2 is sufficient;
+ // One call to get the size and one call to get the actual parameters.
+ // But if one more interface is added or addresses are added,
+ // the call again fails with BUFFER_OVERFLOW.
+ // So the number is picked slightly greater than 2.
+ // We use i <5 in the example
+ for (i = 0; i < 5; i++) {
+ RetVal = GetAdaptersAddresses(
+ AF_INET, 0, NULL,
+ AdapterAddresses,
+ &OutBufferLength);
+
+ if (RetVal != ERROR_BUFFER_OVERFLOW) {
+ break;
+ }
+
+ if (AdapterAddresses != NULL) {
+ free(AdapterAddresses);
+ }
+
+ AdapterAddresses = (PIP_ADAPTER_ADDRESSES) malloc(OutBufferLength);
+ if (AdapterAddresses == NULL) {
+ RetVal = GetLastError();
+ break;
+ }
+ }
+ if (RetVal == NO_ERROR) {
+ // If successful, return pointer to structure
+ return AdapterAddresses;
+ }
+ else {
+ LPVOID MsgBuf;
+
+ printf("Call to GetAdaptersAddresses failed.\n");
+ if (FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ RetVal,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &MsgBuf,
+ 0,
+ NULL )) {
+ printf("\tError: %s", MsgBuf);
+ }
+ LocalFree(MsgBuf);
+ }
+ return NULL;
+}
+
+/*
+ * Set BMC MAC corresponding to current BMC IP address (Windows).
+ */
+static int GetLocalMACByIP() {
+ PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL;
+ PIP_ADAPTER_ADDRESSES AdapterList;
+ int result = 0;
+
+ struct sockaddr_in *si;
+
+ AdapterAddresses = GetAdapters();
+ AdapterList = AdapterAddresses;
+
+ while (AdapterList) {
+ PIP_ADAPTER_UNICAST_ADDRESS addr;
+ addr = AdapterList->FirstUnicastAddress;
+ if (addr == NULL) si = NULL;
+ else si = (struct sockaddr_in*)addr->Address.lpSockaddr;
+ if (si != NULL) {
+ if(memcmp(&si->sin_addr.s_addr, rgmyip, 4) == 0) {
+ memcpy(rgmymac, AdapterList->PhysicalAddress, MAC_LEN);
+ result = 1;
+ break;
+ }
+ }
+ AdapterList = AdapterList->Next;
+ }
+
+ if (AdapterAddresses != NULL) {
+ free(AdapterAddresses);
+ }
+ return result;
+}
+
+/*
+ * Set BMC MAC corresponding to current BMC IP address (Windows).
+ */
+static int GetLocalIPByMAC(uchar *macadr) {
+ PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL;
+ PIP_ADAPTER_ADDRESSES AdapterList;
+ int result = 0;
+
+ struct sockaddr_in *si;
+
+ AdapterAddresses = GetAdapters();
+ AdapterList = AdapterAddresses;
+
+ while (AdapterList) {
+ PIP_ADAPTER_UNICAST_ADDRESS addr;
+ if(memcmp(AdapterList->PhysicalAddress, macadr, MAC_LEN) == 0) {
+ addr = AdapterList->FirstUnicastAddress;
+
+ si = (struct sockaddr_in*)addr->Address.lpSockaddr;
+ if (fdebug) {
+ uchar *psaddr;
+ psaddr = (uchar *)&si->sin_addr.s_addr;
+ printf("mac match: rgmyip=%d.%d.%d.%d s_addr=%d.%d.%d.%d\n",
+ rgmyip[0], rgmyip[1], rgmyip[2], rgmyip[3],
+ psaddr[0], psaddr[1], psaddr[2], psaddr[3]);
+ }
+ if (!IpIsValid(rgmyip) && (fsharedMAC==1)) /*not specified, shared*/
+ memcpy(rgmyip, &si->sin_addr.s_addr, 4);
+ memcpy(osmyip, &si->sin_addr.s_addr, 4);
+ memcpy(osmymac, AdapterList->PhysicalAddress, MAC_LEN);
+ wcstombs(ifname,AdapterList->FriendlyName, sizeof(ifname));
+ result = 1;
+ break;
+ }
+ AdapterList = AdapterList->Next;
+ }
+
+ if (AdapterAddresses != NULL) {
+ free(AdapterAddresses);
+ }
+ return result;
+}
+
+/*
+ * Set MAC and IP address from given interface name (Windows).
+ */
+static int GetLocalDataByIface() {
+ PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL;
+ PIP_ADAPTER_ADDRESSES AdapterList;
+ int result = 0;
+
+ size_t origsize, newsize, convertedChars;
+ wchar_t* wcstring;
+ struct sockaddr_in *si;
+
+ AdapterAddresses = GetAdapters();
+ AdapterList = AdapterAddresses;
+
+ origsize = strlen(ifname) + 1;
+ newsize = origsize;
+ convertedChars = 0;
+ wcstring = (wchar_t*) malloc(sizeof(wchar_t) * newsize) ;
+ if (wcstring == NULL) AdapterList = NULL; /*skip loop, do free*/
+ else mbstowcs(wcstring, ifname, origsize );
+
+ while (AdapterList) {
+ PIP_ADAPTER_UNICAST_ADDRESS addr;
+ if(wcsstr(AdapterList->FriendlyName, wcstring)) {
+ printf("Using interface: %S\n", AdapterList->FriendlyName);
+ printf("\t%S\n", AdapterList->Description);
+ addr = AdapterList->FirstUnicastAddress;
+
+ si = (struct sockaddr_in*)addr->Address.lpSockaddr;
+ memcpy(rgmyip, &si->sin_addr.s_addr, 4);
+ memcpy(rgmymac, AdapterList->PhysicalAddress, MAC_LEN);
+
+ result = 1;
+ break;
+ }
+ AdapterList = AdapterList->Next;
+ }
+
+ if (AdapterAddresses != NULL) {
+ free(AdapterAddresses);
+ }
+ return result;
+}
+
+static int FindEthNum(uchar *macadrin)
+{
+ int i;
+ uchar macadr[MAC_LEN];
+ memcpy(macadr,macadrin,MAC_LEN);
+ if (fsharedMAC == 0 && vend_id == VENDOR_INTEL) {
+ /* Intel factory assigns them this way, so use that to compare */
+ macadr[MAC_LEN-1] -= 2; /*OS MAC = BMC MAC - 2*/
+ }
+ i = GetLocalIPByMAC(macadr);
+ if (fdebug) /* show the local OS eth if and MAC */
+ printf("FindEth: OS %s IP=%d.%d.%d.%d MAC=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ ifname, rgmyip[0], rgmyip[1], rgmyip[2], rgmyip[3],
+ rgmymac[0], rgmymac[1], rgmymac[2], rgmymac[3],
+ rgmymac[4], rgmymac[5]);
+ /* The actual Windows ethernet interface is determined
+ * in Get_IPMac_Addr using ipconfig, so
+ * init eth interface number as eth0 for Windows. */
+ return(i);
+}
+#elif defined(HPUX)
+static int FindEthNum(uchar *macadrin)
+{
+ return(0);
+}
+#else
+/* Linux, BSD, Solaris */
+static char *get_ifreq_mac(struct ifreq *ifrq)
+{
+ char *ptr;
+#ifdef SOLARIS
+ ptr = (char *)&ifrq->ifr_ifru.ifru_enaddr[0];
+#elif BSD
+ ptr = (char *)&ifrq->ifr_ifru.ifru_addr.sa_data[0];
+#elif MACOS
+ static uchar mactmp[MAC_LEN];
+ ptr = &mactmp[0];
+ MacSetInvalid(ptr);
+#else
+ ptr = (char *)&ifrq->ifr_hwaddr.sa_data[0];
+#endif
+ return (ptr);
+}
+
+
+static int FindEthNum(uchar *macadrin)
+{ /*only used for Linux*/
+ struct ifreq ifr;
+ int skfd;
+ int nCurDevice;
+ uchar macadr[MAC_LEN];
+ char szDeviceName[ 16 ]; /* sizeof(ifpattn), MAX_DEVICE_NAME_LENGTH + 1 */
+ int devnum = -1;
+ int n;
+
+ memcpy(macadr,macadrin,MAC_LEN);
+ if (fsharedMAC == 0 && vend_id == VENDOR_INTEL) {
+ /* Intel factory assigns them this way, so use that to compare */
+ macadr[MAC_LEN-1] -= 2; /*OS MAC = BMC MAC - 2*/
+ }
+ n = find_ifname(szDeviceName);
+ if (n >= 0) {
+ n = strlen_(szDeviceName);
+ if (n < sizeof(ifpattn)) {
+ strcpy(ifname0,szDeviceName);
+ strcpy(ifpattn,szDeviceName);
+ ifpattn[n - 1] = 0; /*truncate last digit*/
+ }
+ if (fdebug)
+ printf("found ifname %s, pattern %s\n",szDeviceName,ifpattn);
+ }
+
+ if ( ( skfd = socket(AF_INET, SOCK_DGRAM, 0 ) ) < 0) {
+ if ( fdebug ) {
+ perror("socket");
+ return devnum;
+ }
+ }
+
+ for( nCurDevice = 0 ;
+ (nCurDevice < NUM_DEVICES_TO_CHECK) && (devnum == -1);
+ nCurDevice++ )
+ {
+ sprintf( szDeviceName, "%s%d", ifpattn, nCurDevice );
+ strcpy(ifr.ifr_name, szDeviceName );
+#ifdef SIOCGIFHWADDR
+ if (ioctl(skfd, SIOCGIFHWADDR, &ifr) > 0) {
+ if ( fdebug )
+ printf("FindEthNum: Could not get MAC address for %s\n",
+ szDeviceName);
+ } else
+#endif
+ {
+ if (memcmp(get_ifreq_mac(&ifr), macadr, MAC_LEN) == 0) {
+ devnum = nCurDevice;
+ break;
+ }
+ }
+ }
+ close(skfd);
+ return(devnum);
+}
+#endif
+
+/*
+ * GetBmcEthDevice
+ * Attempt to auto-detect the BMC LAN channel and matching OS eth port.
+ * INPUT: lan_parm = lan channel from user -L option, 0xFF if not specified
+ * OUTPUT: lan_ch is set to BMC LAN channel number
+ * if success, returns index of OS eth port (0, 1, ...).
+ * if no lan channels found, returns -2.
+ * if other error, returns -1.
+ */
+static int GetBmcEthDevice(uchar lan_parm)
+{
+ uchar LanRecord[30];
+ int devnum = -1;
+ int ret;
+ uchar bmcMacAddress[ MAC_LEN ]; /*MAC_LEN = 6*/
+ int rlen;
+ uchar iData[2];
+ uchar rData[10];
+ uchar cc;
+ int i = 0;
+ int j, jstart, jend, jlan;
+ uchar mtype;
+ uchar *pb;
+ int fchgmac;
+
+ /* Find the LAN channel(s) via Channel Info */
+ if (lan_parm < MAXCHAN) { /* try user-specified channel only */
+ lan_ch = lan_parm;
+ jstart = lan_parm;
+ jend = lan_parm+1;
+ } else {
+ jstart = 1;
+ jend = MAXCHAN;
+ for (j = 0; j < MAXCHAN; j++) chan_type[j] = 0;
+ }
+ memset(bmcMacAddress,0xff,sizeof(bmcMacAddress)); /*initialize to invalid*/
+ for (j = jstart; j < jend; j++) {
+ rlen = sizeof(rData);
+ iData[0] = (uchar)j; /*channel #*/
+ memset(rData,0,9); /*initialize recv data*/
+ ret = ipmi_cmd(GET_CHANNEL_INFO, iData, 1, rData, &rlen, &cc, fdebug);
+ if (ret == 0xcc || cc == 0xcc) /* special case for ipmi_lan */
+ continue;
+ if (ret != 0) {
+ if (fdebug) printf("get_chan_info rc = %x\n",ret);
+ break;
+ }
+ mtype = rData[1]; /* channel medium type */
+ chan_type[j] = mtype;
+ if (mtype == 4) { /* 802.3 LAN type*/
+ if (fdebug) printf("chan[%d] = lan\n",j);
+ jlan = lan_ch; /*save prev lan chan */
+ /* Get BMC MAC for this LAN channel. */
+ /* Note: BMC MAC may not be valid yet. */
+ lan_ch = (uchar)j; /*set lan channel for GetLanEntry()*/
+ ret = GetLanEntry( 5 /*MAC_ADDRESS_LAN_PARAM*/,0, LanRecord);
+ if ( ret < 0 ) {
+ lan_ch = (uchar)jlan; /*restore lan_ch*/
+ printf( "GetBmcEthDevice: GetLanEntry failed\n" );
+ return devnum;
+ }
+ pb = &LanRecord[0];
+ if (fdebug) printf("chan[%d] BMC MAC %x:%x:%x:%x:%x:%x\n",j,
+ pb[0], pb[1], pb[2], pb[3], pb[4], pb[5] );
+ fchgmac = 0;
+ if (!MacIsValid(bmcMacAddress)) /* old MAC not valid */
+ fchgmac = 1;
+ else if (MacIsValid(pb) && /* new MAC is valid and */
+ (memcmp(bmcMacAddress,pb, sizeof(bmcMacAddress)) > 0))
+ fchgmac = 1; /* new MAC lower */
+ if (fchgmac) { /* use lowest valid MAC */
+ memcpy(bmcMacAddress,pb,sizeof(bmcMacAddress));
+ lan_ch = (uchar)j;
+ } else lan_ch = (uchar)jlan; /* restore prev lan chan */
+ i++; /* i = num lan channels found */
+ } else if (mtype == 5) { /* serial type*/
+ if (fdebug) printf("chan[%d] = serial\n",j);
+ ser_ch = (uchar)j; /* set to last serial channel */
+ } else if (mtype == 7) { /* PCI SMBus */
+ if (fdebug) printf("chan[%d] = pci_smbus\n",j);
+ } else if (mtype == 12) { /* system interface */
+ if (fdebug) printf("chan[%d] = system_interface\n",j);
+ } else /* other channel medium types, see IPMI 1.5 Table 6-3 */
+ if (fdebug) printf("chan[%d] = %d\n",j,mtype);
+ }
+ nlans = i;
+ if (i == 0) return(-2); /* no lan channels found */
+ if (fdebug) printf("lan_ch detected = %d\n",lan_ch);
+
+ devnum = FindEthNum(bmcMacAddress);
+ if ( fdebug )
+ printf("GetBmcEthDevice: channel %d, %s%d\n",lan_ch,ifpattn,devnum);
+ return devnum;
+}
+
+/*
+ * atomac - converts ASCII string to binary MAC address (array).
+ * Accepts input formatted as 11:22:33:44:55:66 or 11-22-33-44-55-66.
+ */
+static void atomac(uchar *array, char *instr)
+{
+ int i,j,n;
+ char *pi;
+ j = 0;
+ pi = instr;
+ n = strlen_(instr);
+ for (i = 0; i <= n; i++) {
+ if (instr[i] == ':') {
+ array[j++] = htoi(pi);
+ pi = &instr[i+1];
+ } else if (instr[i] == '-') {
+ array[j++] = htoi(pi);
+ pi = &instr[i+1];
+ } else if (instr[i] == 0) {
+ array[j++] = htoi(pi);
+ }
+ if (j >= MAC_LEN) break; /*safety valve*/
+ }
+ if (fdebug)
+ printf("atomac: %02x %02x %02x %02x %02x %02x\n",
+ array[0],array[1],array[2],array[3], array[4],array[5]);
+} /*end atomac()*/
+
+/* file_grep/findmatch no longer used here, see ievents.c */
+
+/*
+ * Get_Mac
+ * This routine finds a MAC address from a given IP address.
+ * Usually for the Alert destination.
+ * It uses ARP cache to do this.
+ */
+#ifdef WIN32
+static int Get_Mac(uchar *ipadr,uchar *macadr)
+{
+ DWORD dwRetVal;
+ IPAddr DestIp = 0;
+ IPAddr SrcIp = 0; /* default for src ip */
+ ULONG MacAddr[2]; /* for 6-byte hardware addresses */
+ ULONG PhysAddrLen = MAC_LEN; /* default to length of six bytes */
+ BYTE *bPhysAddr;
+
+
+ memcpy(&DestIp, ipadr, 4);
+
+ /* invoke system ARP query */
+ dwRetVal = SendARP(DestIp, SrcIp, MacAddr, &PhysAddrLen);
+
+ if (dwRetVal == NO_ERROR)
+ { /* no error - get the MAC */
+ bPhysAddr = (BYTE *) & MacAddr;
+ if (PhysAddrLen) {
+ memcpy(macadr, bPhysAddr, MAC_LEN);
+ } else
+ printf("Warning: SendArp completed successfully, but returned length=0\n");
+ } else if (dwRetVal == ERROR_GEN_FAILURE)
+ { /* MAC not available in this netowork - get gateway MAC */
+ memcpy(macadr, rggwymac, MAC_LEN);
+ } else
+ { /* other errors */
+ printf("Error: SendArp failed with error: %d", dwRetVal);
+ switch (dwRetVal) {
+ case ERROR_INVALID_PARAMETER:
+ printf(" (ERROR_INVALID_PARAMETER)\n");
+ break;
+ case ERROR_INVALID_USER_BUFFER:
+ printf(" (ERROR_INVALID_USER_BUFFER)\n");
+ break;
+ case ERROR_BAD_NET_NAME:
+ printf(" (ERROR_GEN_FAILURE)\n");
+ break;
+ case ERROR_BUFFER_OVERFLOW:
+ printf(" (ERROR_BUFFER_OVERFLOW)\n");
+ break;
+ case ERROR_NOT_FOUND:
+ printf(" (ERROR_NOT_FOUND)\n");
+ break;
+ default:
+ printf("\n");
+ break;
+ }
+ return 1;
+ }
+ return 0;
+} /* end Get_Mac()*/
+/*endif WIN32 */
+#else
+/*else Linux */
+static int Get_Mac(uchar *ipadr,uchar *macadr)
+{
+ FILE *fparp;
+ char buff[1024];
+ /* char arpfile[] = "/proc/net/arp"; */
+ char alertfile[] = "/tmp/dest.arping";
+ char arping_cmd[128];
+ char *pb, *pm, *px;
+ int num, i;
+ int foundit = 0;
+ int ret = 0;
+ char *_ifname;
+
+ if (strcmp(ifname,"gcm") == 0) _ifname = ifname0;
+ else _ifname = ifname;
+
+ /* Get a MAC address for a given IP address */
+ if (ipadr[0] != 0) { /* if valid IP address */
+
+ /* make sure the destination is in the arp cache */
+ sprintf(arping_cmd,
+ "arping -I %s -c 2 %d.%d.%d.%d |grep reply |tail -n1 >%s\n",
+ _ifname,ipadr[0],ipadr[1],ipadr[2],ipadr[3],alertfile);
+ if (fdebug) printf("%s", arping_cmd);
+ system(arping_cmd);
+
+ fparp = fopen(alertfile,"r");
+ if (fparp == NULL) {
+ fprintf(stdout,"Get_Mac: Cannot open %s, errno = %d\n",
+ alertfile,get_errno());
+ ret = -1;
+ } else {
+ while (fgets(buff, 1023, fparp)) {
+ /* should only run through loop once */
+ num = strcspn(buff," \t"); /* skip 1st word ("Unicast") */
+ i = strspn(&buff[num]," \t");
+ pb = &buff[num+i];
+ if (strncmp(pb,"reply",5) == 0) { /* valid output */
+ /* Find the ip address */
+ pb += 6 + 5; /* skip "reply from " */
+ num = strcspn(pb," \t");
+ pb[num] = 0;
+ if (fdebug) printf("Alert ip=%s\n",pb);
+ /* IP address should already match input param */
+ /* if (rgdestip[0] == 0) atoip(rgdestip,pb); */
+ /* Now find the mac address */
+ pm = strchr(&pb[num+1],'[');
+ if (pm == NULL) pm = &pb[num+2]; /* just in case */
+ pm++;
+ px = strchr(pm,']');
+ if (px == NULL) px = pm + 17; /* just in case */
+ px[0] = 0;
+ if (fdebug) printf("Alert mac=%s\n",pm);
+ foundit = 1;
+ if (!MacIsValid(macadr)) atomac(macadr,pm);
+ break;
+ }
+ } /*end while*/
+ fclose(fparp);
+ } /*end else file opened*/
+ } /*endif valid IP */
+ else ret = -1;
+
+ if (ret == -1 || foundit == 0) { /* couldn't get it */
+ if (MacIsValid(rggwymac) && !MacIsValid(rgdestmac))
+ memcpy(rgdestmac,rggwymac,6); /* get to it from the default gateway */
+ }
+ return(ret);
+} /* end Get_Mac()*/
+/*end else Linux*/
+#endif
+
+#ifdef WIN32
+
+/*
+ * Set subnet mask based on current IP address (Windows).
+ */
+static int SetSubnetMask() {
+ PMIB_IPADDRTABLE pIPAddrTable;
+ unsigned int i;
+ DWORD dwSize = 0, dwRetVal;
+ LPVOID lpMsgBuf;
+
+ pIPAddrTable = (MIB_IPADDRTABLE*) malloc( sizeof( MIB_IPADDRTABLE) );
+
+ if ( pIPAddrTable ) {
+ // Make an initial call to GetIpAddrTable to get the
+ // necessary size into the dwSize variable
+ if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
+ free( pIPAddrTable );
+ pIPAddrTable = (MIB_IPADDRTABLE *) malloc ( dwSize );
+ }
+ } else
+ printf("Memory allocation failed.\n");
+
+ if ( pIPAddrTable ) {
+ // Make a second call to GetIpAddrTable to get the
+ // actual data we want
+ if ( (dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 )) == NO_ERROR ) {
+ for(i = 0; i < pIPAddrTable->dwNumEntries; ++i) {
+ if(memcmp(&(pIPAddrTable->table[i].dwAddr), rgmyip, 4) == 0) {
+ memcpy(rgsubnet, &(pIPAddrTable->table[i].dwMask), 4);
+ free( pIPAddrTable );
+ return 1;
+ }
+ }
+ } else {
+ if (FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ dwRetVal,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL )) {
+ printf("\tError: %s", lpMsgBuf);
+ }
+
+ printf("Call to GetIpAddrTable failed.\n");
+ }
+ }
+
+ if ( pIPAddrTable )
+ free( pIPAddrTable );
+
+ return 0;
+}
+
+/*
+ * Extract gateway address from routing table (Windows).
+ */
+static int SetDefaultGateway() {
+ PMIB_IPFORWARDTABLE pIpForwardTable;
+ DWORD dwRetVal, dwSize;
+
+ unsigned int nord_mask;
+ unsigned int nord_ip;
+ unsigned int nord_net;
+
+ unsigned int i;
+
+ nord_mask = *((unsigned int *)rgsubnet);
+ nord_ip = *((unsigned int *)rgmyip);
+
+ nord_net = nord_ip & nord_mask;
+
+ pIpForwardTable = (MIB_IPFORWARDTABLE*) malloc(sizeof(MIB_IPFORWARDTABLE));
+ if (pIpForwardTable == NULL) {
+ printf("Error allocating memory\n");
+ return 0;
+ }
+
+ dwSize = 0;
+ if (GetIpForwardTable(pIpForwardTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
+ free(pIpForwardTable);
+ pIpForwardTable = (MIB_IPFORWARDTABLE*) malloc(dwSize);
+ if (pIpForwardTable == NULL) {
+ printf("Error allocating memory\n");
+ return 0;
+ }
+ }
+
+ /*
+ * Note that the IPv4 addresses returned in
+ * GetIpForwardTable entries are in network byte order
+ */
+ if ((dwRetVal = GetIpForwardTable(pIpForwardTable, &dwSize, 0)) == NO_ERROR) {
+ for (i = 0; i < (int) pIpForwardTable->dwNumEntries; i++) {
+ unsigned int gwaddr = pIpForwardTable->table[i].dwForwardNextHop;
+ if(nord_net == (gwaddr & nord_mask) && nord_ip != gwaddr)
+ { /* searching for gateways from our network with different address than ours */
+ memcpy(rggwyip, &gwaddr, 4);
+ return 0;
+ }
+ }
+ free(pIpForwardTable);
+ return 1;
+ }
+ else {
+ printf("\tGetIpForwardTable failed.\n");
+ free(pIpForwardTable);
+ return 0;
+ }
+
+}
+/*endif WIN32*/
+#endif
+
+static int ShowChanAcc(uchar bchan)
+{
+ uchar LanRecord[30];
+ int ret = 0;
+
+ ret = GetChanAcc(bchan, 0x40, LanRecord);
+ if (fdebug)
+ printf(" GetChanAcc(%d) ret = %d, data = %02x %02x\n",
+ bchan,ret, LanRecord[0], LanRecord[1]);
+ if (ret == 0)
+ fprintf(fd_bmc,"ChannelAccess %d%c %02x %02x \n",
+ bchan,bdelim,LanRecord[0],LanRecord[1]);
+ return(ret);
+}
+
+static int GetSerialOverLan( uchar chan, uchar bset, uchar block )
+{
+ uchar requestData[24];
+ uchar rData[MAX_BUFFER_SIZE];
+ int rlen;
+ int status, i;
+ uchar ccode;
+ uchar enable_parm, auth_parm, baud_parm;
+ uchar user;
+
+ if (fIPMI20 && fSOL20) {
+ getsolcmd = GET_SOL_CONFIG2;
+ enable_parm = SOL_ENABLE_PARAM;
+ auth_parm = SOL_AUTHENTICATION_PARAM;
+ baud_parm = SOL_BAUD_RATE_PARAM;
+ } else {
+ getsolcmd = GET_SOL_CONFIG;
+ enable_parm = SOL_ENABLE_PARAM;
+ auth_parm = SOL_AUTHENTICATION_PARAM;
+ baud_parm = SOL_BAUD_RATE_PARAM;
+ chan = 0; /*override chan for IPMI 1.5*/
+ }
+ printf("%c## %s, GetSOL for channel %d ...\n",bcomment,progname,chan);
+
+ requestData[0] = chan; /*channel*/
+ requestData[1] = enable_parm;
+ requestData[2] = bset; /*set*/
+ requestData[3] = block; /*block*/
+ rlen = sizeof(rData);
+ status = ipmi_cmd(getsolcmd, requestData,4, rData, &rlen,&ccode,fdebug);
+ if (status != 0) return(status);
+ if (ccode) {
+ if (ccode == 0xC1) { /* unsupported command */
+ printf("%c Serial-Over-Lan not available on this platform\n",
+ bcomment);
+ return(status);
+ } else {
+ printf("%c SOL Enable ccode = %x\n",bcomment,ccode);
+ status = ccode;
+ }
+ } else { /*success*/
+ fprintf(fd_bmc,"SOLParam %d,%d,%d%c",chan,enable_parm,bset,bdelim);
+ for (i = 1; i < rlen; i++) fprintf(fd_bmc," %02x",rData[i]);
+ fprintf(fd_bmc,"\n");
+ }
+
+ requestData[0] = chan;
+ requestData[1] = auth_parm;
+ requestData[2] = bset; // selector
+ requestData[3] = block; // block
+ rlen = sizeof(rData);
+ status = ipmi_cmd(getsolcmd, requestData,4,rData, &rlen,&ccode,fdebug);
+ if (status != 0) return(status);
+ if (ccode) {
+ printf("%c SOL Auth ccode = %x\n",bcomment,ccode);
+ status = ccode;
+ } else { /*success*/
+ fprintf(fd_bmc,"SOLParam %d,%d,%d%c",chan,auth_parm,bset,bdelim);
+ for (i = 1; i < rlen; i++) fprintf(fd_bmc," %02x",rData[i]);
+ fprintf(fd_bmc,"\n");
+ }
+
+ requestData[0] = chan;
+ requestData[1] = SOL_ACC_INTERVAL_PARAM;
+ requestData[2] = bset;
+ requestData[3] = block;
+ rlen = sizeof(rData);
+ status = ipmi_cmd(getsolcmd, requestData,4,rData, &rlen,&ccode,fdebug);
+ if (status != 0) return(status);
+ if (ccode) {
+ printf("%c SOL Accum Interval ccode = %x\n",bcomment,ccode);
+ status = ccode;
+ } else { /*success*/
+ fprintf(fd_bmc,"SOLParam %d,%d,%d%c",chan,SOL_ACC_INTERVAL_PARAM,bset,bdelim);
+ for (i = 1; i < rlen; i++) fprintf(fd_bmc," %02x",rData[i]);
+ fprintf(fd_bmc,"\n");
+ }
+
+ requestData[0] = chan;
+ requestData[1] = SOL_RETRY_PARAM;
+ requestData[2] = bset;
+ requestData[3] = block;
+ rlen = sizeof(rData);
+ status = ipmi_cmd(getsolcmd, requestData,4,rData, &rlen,&ccode,fdebug);
+ if (status != 0) return(status);
+ if (ccode) {
+ printf("%c SOL Retry ccode = %x\n",bcomment,ccode);
+ status = ccode;
+ } else { /*success*/
+ fprintf(fd_bmc,"SOLParam %d,%d,%d%c",chan,SOL_RETRY_PARAM,bset,bdelim);
+ for (i = 1; i < rlen; i++) fprintf(fd_bmc," %02x",rData[i]);
+ fprintf(fd_bmc,"\n");
+ }
+
+ if (!fRomley) {
+ requestData[0] = chan;
+ requestData[1] = baud_parm;
+ requestData[2] = bset;
+ requestData[3] = block;
+ rlen = sizeof(rData);
+ status = ipmi_cmd(getsolcmd,requestData,4,rData,&rlen,&ccode,fdebug);
+ if (status != 0) return(status);
+ if (ccode) {
+ printf("%c SOL nvol Baud ccode = %x\n",bcomment,ccode);
+ status = ccode;
+ } else { /*success*/
+ fprintf(fd_bmc,"SOLParam %d,%d,%d%c",chan,baud_parm,bset,bdelim);
+ for (i = 1; i < rlen; i++) fprintf(fd_bmc," %02x",rData[i]);
+ fprintf(fd_bmc,"\n");
+ }
+
+ requestData[0] = chan;
+ requestData[1] = SOL_VOL_BAUD_RATE_PARAM; /*0x06*/
+ requestData[2] = bset;
+ requestData[3] = block;
+ rlen = sizeof(rData);
+ status = ipmi_cmd(getsolcmd,requestData,4,rData,&rlen,&ccode,fdebug);
+ if (status != 0) return(status);
+ if (ccode) {
+ printf("%c SOL vol Baud ccode = %x\n",bcomment,ccode);
+ status = ccode;
+ } else { /*success*/
+ fprintf(fd_bmc,"SOLParam %d,%d,%d%c",chan,SOL_VOL_BAUD_RATE_PARAM,bset,bdelim);
+ for (i = 1; i < rlen; i++) fprintf(fd_bmc," %02x",rData[i]);
+ fprintf(fd_bmc,"\n");
+ }
+ }
+
+ if (fIPMI20) {
+ requestData[0] = chan;
+ rlen = sizeof(rData);
+ status = ipmi_cmdraw(GET_PAYLOAD_SUPPORT, NETFN_APP,
+ BMC_SA,PUBLIC_BUS,BMC_LUN,
+ requestData,1,rData, &rlen, &ccode, fdebug);
+ if ((status != 0) || (ccode != 0)) {
+ printf("%c SOL Payload Support(%d) error %d, ccode = %x\n",
+ bcomment,chan,status,ccode);
+ if (status == 0) status = ccode;
+ } else { /*success*/
+ fprintf(fd_bmc,"SOLPayloadSupport %d%c",chan,bdelim);
+ for (i = 1; i < rlen; i++) fprintf(fd_bmc," %02x",rData[i]);
+ fprintf(fd_bmc,"\n");
+ }
+ /* get Payload Access for nusers, not just lan_user */
+ for (user = 1; user <= nusers; user++)
+ {
+ /* IPMI 2.0 nusers >= 4 users */
+ requestData[0] = chan;
+ requestData[1] = user;
+ rlen = sizeof(rData);
+ status = ipmi_cmdraw(GET_PAYLOAD_ACCESS, NETFN_APP,
+ BMC_SA,PUBLIC_BUS,BMC_LUN,
+ requestData,2,rData, &rlen, &ccode, fdebug);
+ if ((status != 0) || (ccode != 0)) {
+ printf("%c SOL Payload Access(%d,%d) error %d, ccode = %x\n",
+ bcomment,chan,user,status,ccode);
+ if (status == 0) status = ccode;
+ } else { /*success*/
+ fprintf(fd_bmc,"SOLPayloadAccess %d,%d%c",chan,user,bdelim);
+ for (i = 0; i < rlen; i++) fprintf(fd_bmc," %02x",rData[i]);
+ fprintf(fd_bmc,"\n");
+ }
+ } /*end user loop*/
+ }
+
+ return(status);
+} /*end GetSerialOverLan */
+
+static char *PefDesc(int idx, uchar stype)
+{
+ char *pdesc;
+ if (pefdesc == NULL) pdesc = "reserved";
+ else pdesc = pefdesc[idx];
+ if ((stype != 0) && (strcmp(pdesc,"reserved") == 0)) {
+ /* pefdesc may not match on some non-Intel systems. */
+ /* so use sensor type */
+ switch(stype) {
+ case 0x01: pdesc = "Temperature"; break;
+ case 0x02: pdesc = "Voltage"; break;
+ case 0x04: pdesc = "Fan"; break;
+ case 0x05: pdesc = "Chassis"; break;
+ case 0x07: pdesc = "BIOS"; break;
+ case 0x08: pdesc = "Power Supply"; break;
+ case 0x09: pdesc = "Power Unit"; break;
+ case 0x0c: pdesc = "Memory"; break;
+ case 0x0f: pdesc = "Boot"; break;
+ case 0x12: pdesc = "System Restart"; break;
+ case 0x13: pdesc = "NMI"; break;
+ case 0x23: pdesc = "Watchdog"; break;
+ case 0x20: pdesc = "OS Critical Stop"; break;
+ default: pdesc = "Other"; break;
+ }
+ }
+ return(pdesc);
+}
+
+static int GetSessionInfo(uchar *rData, int sz)
+{
+ int rv, rlen;
+ uchar ccode;
+ uchar iData[5];
+
+ iData[0] = 0x00; /*get data for this session*/
+ rlen = sz;
+ rv = ipmi_cmdraw(CMD_GET_SESSION_INFO,NETFN_APP, BMC_SA,PUBLIC_BUS,BMC_LUN,
+ iData,1,rData, &rlen, &ccode, fdebug);
+ if ((rv == 0) && (ccode != 0)) rv = ccode;
+ return(rv);
+}
+
+static int GetPefCapabilities(uchar *bmax)
+{
+ int rv, rlen;
+ uchar ccode;
+ uchar rData[MAX_BUFFER_SIZE];
+
+ rlen = sizeof(rData);
+ rv = ipmi_cmdraw(0x10, NETFN_SEVT, BMC_SA,PUBLIC_BUS,BMC_LUN,
+ NULL,0,rData, &rlen, &ccode, fdebug);
+ if ((rv == 0) && (ccode != 0)) rv = ccode;
+ if ((rv == 0) && (bmax != NULL))
+ *bmax = rData[2]; /*max num PEF table entries*/
+ return(rv);
+}
+
+int WaitForSetComplete(int limit)
+{
+ int rv = 0;
+ int i;
+ uchar bdata[4];
+
+ for (i = 0; i < limit; i++) {
+ rv = GetLanEntry(0, 0, bdata);
+ if (fdebug) printf("WaitForSetComplete(%d): i=%d rv=%d val=%x\n",
+ limit,i,rv,bdata[1]);
+ if ((rv == 0) && (bdata[1] == 0)) break;
+ else os_usleep(0,100);
+ }
+ return(rv);
+}
+
+int SerialIsOptional(int bparam)
+{
+ /* These Serial Parameters are for optional Modem/Callback functions. */
+ int optvals[9] = { 5, 9, 10, 11, 12, 13, 14, 20, 21 };
+ int rv = 0;
+ int i;
+ for (i = 0; i < sizeof(optvals); i++) {
+ if (optvals[i] == bparam) { rv = 1; break; }
+ }
+ return(rv);
+}
+
+static int parse_line(char *line, char *keyret, char *value)
+{
+ char *eol;
+ char *key;
+ char *val;
+ int i, n;
+
+ key = &line[0];
+ eol = &line[strlen(line)];
+ while( *key < 0x21 && key < eol )
+ key++; /*remove leading whitespace */
+ if( key[0] == bcomment ) return 2; /*skip comments */
+ /*
+ * find the value set, delimited by bdelim (':' or '|')
+ */
+ val = strchr( line, bdelim );
+ if( val == NULL ) return 1; /* skip if empty or no delimeter */
+ val[0] = 0; /*stringify the key*/
+ val++;
+ while( val[0] < 0x21 && val < eol )
+ val++; /*remove leading whitespace */
+ /*
+ * truncate trailing newline/whitespace after last word
+ */
+ n = strlen_( val );
+ for( i = n; i >= 0; i-- ) /*decrease from end*/
+ if( val[i] >= 0x21 ) break; /*found last valid char */
+ if (i < n) val[i + 1] = 0;
+
+ strcpy(keyret, key); /*has keyword and params*/
+ strcpy(value, val); /*has list of hex values*/
+ return 0;
+}
+
+#ifdef METACOMMAND
+int i_config(int argc, char **argv)
+#else
+#ifdef WIN32
+int __cdecl
+#else
+int
+#endif
+main(int argc, char **argv)
+#endif
+{
+ int ret;
+ PEF_RECORD *pPefRecord;
+ PEF_RECORD PefRecord;
+ uchar LanRecord[64];
+ uchar bParams[5];
+ char filename[80] = "";
+ int i, j, c, n;
+ uchar idx;
+ // char *pstr;
+ uchar bset = 0;
+ int ndest = 4;
+ int idest;
+ // char mystr[80];
+ uchar * pc; int sz;
+ char line[240]; /* hdr(18) + data(192 = 64 * 3) + '\0' = 211 */
+ char key[40];
+ char value[100];
+ uchar rData[50];
+ int rlen;
+ uchar cc;
+ uchar chan;
+ char *pk;
+ char fpefok = 1;
+ char fignore_err;
+
+ // progname = argv[0];
+ printf("%s ver %s \n",progname,progver);
+ func = 'l'; freadonly = 1; /*list is default*/
+
+ while ((c = getopt(argc, argv,"cdmlr:s:xL:T:V:J:EYF:P:N:R:U:Z:?")) != EOF)
+ switch(c) {
+ case 'c': fcanonical = 1; bdelim = BDELIM; break;
+ case 'd': func = 'd'; freadonly = 0; break; /*set Defaults*/
+ case 'l': func = 'l'; freadonly = 1; break; /*list*/
+ case 'm': fdomac = 1; break; /*restore mac*/
+ case 'r': func = 'r'; freadonly = 0; /*restore*/
+ sz = strlen_(optarg);
+ if (sz > sizeof(filename)) sz = sizeof(filename);
+ strncpy(filename,optarg,sz);
+ break;
+ case 's': func = 's'; freadonly = 1; /*save*/
+ sz = strlen_(optarg);
+ if (sz > sizeof(filename)) sz = sizeof(filename);
+ strncpy(filename,optarg,sz);
+ break;
+ case 'x': fdebug = 1; break;
+ case 'p': /* password to set */
+ fpassword = 1;
+ if (strlen_(optarg) > 16) optarg[16] = 0;
+ strcpy(passwordData,optarg);
+ if (fdebug) printf("Password = %s\n",passwordData);
+ /* Hide password from 'ps' */
+ memset(optarg, ' ', strlen_(optarg));
+ break;
+ case 'L':
+ lan_ch_parm = atob(optarg);
+ if (lan_ch_parm >= MAXCHAN) lan_ch_parm = 0xff; /*invalid*/
+ break;
+ case 'N': /* nodename */
+ case 'U': /* remote username */
+ case 'P': /* remote password */
+ case 'R': /* remote password */
+ case 'E': /* get password from IPMI_PASSWORD environment var */
+ case 'F': /* force driver type */
+ case 'T': /* auth type */
+ case 'J': /* cipher suite */
+ case 'V': /* priv level */
+ case 'Y': /* prompt for remote password */
+ case 'Z': /* set local MC address */
+ parse_lan_options(c,optarg,fdebug);
+ break;
+ default:
+ printf("Usage: %s [-clmpxLNUPREFTJVY -r <file> -s <file>]\n",
+ progname);
+ printf("where -l Lists BMC configuration parameters\n");
+ printf(" -r Restores BMC configuration from <file>\n");
+ printf(" -s Saves BMC configuration to <file>\n");
+ printf(" -c canonical output with delimiter '%c'\n",BDELIM);
+ printf(" -m Set BMC MAC during restore\n");
+ printf(" -x show eXtra debug messages\n");
+ printf(" -p <psw> specify a user password to set\n");
+ printf(" -L 3 specify lan channel number 3\n");
+ print_lan_opt_usage();
+ ret = ERR_USAGE;
+ goto do_exit;
+ }
+
+ switch(func) {
+ case 'l': fd_bmc = stdout; break;
+ case 'r': fd_bmc = fopen(filename,"r"); break;
+ case 's': fd_bmc = fopen(filename,"w"); break;
+ default: break;
+ }
+ if (fd_bmc == NULL) {
+ printf("Error: cannot open %s\n",filename);
+ ret = ERR_FILE_OPEN;
+ fd_bmc = stdout;
+ goto do_exit;
+ }
+ fipmilan = is_remote();
+
+ if (fipmilan) parse_lan_options('V',"4",0);
+
+ ret = GetDeviceID( LanRecord);
+ if (ret != 0) {
+ goto do_exit;
+ } else { /* success */
+ uchar ipmi_maj, ipmi_min;
+ ipmi_maj = LanRecord[4] & 0x0f;
+ ipmi_min = LanRecord[4] >> 4;
+ show_devid( LanRecord[2], LanRecord[3], ipmi_maj, ipmi_min);
+ if (ipmi_maj == 0) fIPMI10 = 1;
+ else if (ipmi_maj == 1 && ipmi_min < 5) fIPMI10 = 1;
+ else fIPMI10 = 0; /* >= IPMI 1.5 is ok */
+ if (ipmi_maj >= 2) fIPMI20 = 1;
+ /* nusers can be up to 15 max */
+ if (fIPMI20) nusers = 5;
+ else nusers = 3;
+ if (fIPMI10) {
+ printf("%c This IPMI v%d.%d system does not support PEF records.\n",
+ bcomment,ipmi_maj,ipmi_min);
+ /* Wont handle PEF, but continue and look for BMC LAN anyway */
+ // fIPMI10 = 1;
+ // ipmi_close_();
+ // exit(1);
+ }
+ prod_id = LanRecord[9] + (LanRecord[10] << 8);
+ vend_id = LanRecord[6] + (LanRecord[7] << 8)
+ + (LanRecord[8] << 16);
+ /* check Device ID response for Manufacturer ID = 0x0322 (NSC) */
+ if (vend_id == VENDOR_NSC) { /* NSC = 0x000322 */
+ fmBMC = 1; /*NSC miniBMC*/
+ if (pefnum == 12) pefnum = 10; /* change CritStop pefnum to 0x0a */
+ pefdesc = &pefdesc2[0];
+ pefmax = 30;
+ fsharedMAC = 1; /*LAN1 shares MAC with OS*/
+ } else if (vend_id == VENDOR_LMC) { /* LMC (on SuperMicro) = 0x000878 */
+ fmBMC = 0;
+ pefdesc = NULL; /* unknown, see PefDesc() */
+ if (pefnum == 12) pefnum = 15; /* change CritStop pefnum */
+ pefmax = 16;
+ fsharedMAC = 0; /* not-shared BMC LAN port */
+ } else if (vend_id == VENDOR_INTEL) { /* Intel = 0x000157 */
+ pefdesc = &pefdesc1[0]; /*Intel defaults*/
+ pefmax = 20; /*Intel default pefmax = 20*/
+ switch(prod_id) {
+ case 0x4311: /* Intel NSI2U*/
+ fmBMC = 1; /* Intel miniBMC*/
+ if (pefnum == 12) pefnum = 14; /* change CritStop pefnum */
+ pefdesc = &pefdesc2[0];
+ pefmax = 30;
+ fsharedMAC = 1; /*LAN1 shares MAC with OS*/
+ break;
+ case 0x0026:
+ case 0x0028:
+ case 0x0811: /* Alcolu & TIGW1U */
+ fmBMC = 0; /* Intel Sahalee BMC*/
+ fsharedMAC = 0; /* not-shared BMC LAN port, separate MAC */
+ gcm_ch = 3;
+ break;
+ case 0x003E: /*NSN2U or CG2100 Urbanna*/
+ fiBMC = 1; /* Intel iBMC */
+ fsharedMAC = 0; /* not-shared BMC LAN port, separate MAC */
+ set_max_kcs_loops(URNLOOPS); /*longer for SetLan cmds (default 300)*/
+ break;
+ case 0x0107: /* Intel Caneland*/
+ fsharedMAC = 0; /* not-shared BMC LAN port, separate MAC */
+ gcm_ch = 3;
+ break;
+ case 0x0022: /* Intel TIGI2U*/
+ fsharedMAC = 1; /*LAN1 shares MAC with OS*/
+ gcm_ch = 3;
+ nusers = 4;
+ break;
+ default: /* else other Intel */
+ if (fIPMI20) fsharedMAC = 0; /* recent, not-shared BMC MAC */
+ else fsharedMAC = 1; /* usu IPMI 1.x has shared BMC MAC */
+#ifdef TEST
+ /* also check for ia64, and set chan_pefon, chan_pefoff accordingly*/
+ if (prod_id == 0x0100) { /* Intel Tiger2, Itanium2 */
+ chan_pefon = CHAN_ACC_PEFON64;
+ chan_pefoff = CHAN_ACC_PEFOFF64;
+ }
+#endif
+ break;
+ } /*end switch*/
+ if (is_romley(vend_id,prod_id)) {
+ fRomley = 1;
+ fiBMC = 1; /* Intel iBMC */
+ fsharedMAC = 0; /* not-shared BMC LAN port, separate MAC */
+ set_max_kcs_loops(URNLOOPS); /*longer for SetLan cmds */
+ fipv6 = 1;
+ }
+ } else if (vend_id == VENDOR_KONTRON) {
+ //if (prod_id == 0x1590) fchan2wart = 1; /* KTC5520 chan2 wart */
+ fsharedMAC = 0; /* not-shared BMC MAC */
+ pefdesc = NULL; /* unknown, see PefDesc() */
+ if (pefnum == 12) pefnum = 15; /* change CritStop pefnum to 15 */
+ } else { /* else other vendors */
+ if (fIPMI20) fsharedMAC = 0; /* recent, not-shared BMC MAC */
+ else fsharedMAC = 1; /* usu IPMI 1.x has shared BMC MAC */
+ fmBMC = 0;
+ pefdesc = NULL; /* unknown, see PefDesc() */
+ if (pefnum == 12) pefnum = 15; /* change CritStop pefnum to 15? */
+ pefmax = 20;
+ }
+ if (fmBMC) nusers = 1;
+ }
+
+ ret = GetPefCapabilities(&bset);
+ if ((ret == 0) && (bset <= MAXPEF)) pefmax = bset;
+
+ /* Get the BMC LAN channel & match it to an OS eth if. */
+ i = GetBmcEthDevice(lan_ch_parm);
+ if (i == -2) { /* no lan channels */
+ printf("This system does not support BMC LAN channels.\n");
+ ret = ERR_NOT_ALLOWED;
+ goto do_exit;
+ } else if (i < 0) { /* mac not found, use platform defaults */
+ i = 0; /* default to eth0, lan_ch set already. */
+ if (vend_id == VENDOR_INTEL) {
+ if ((prod_id == 0x001B) || (prod_id == 0x000c)) {
+ /* Intel TIGPR2U or TSRLT2 defaults are special */
+ if (lan_ch_parm == 6)
+ { i = 0; lan_ch = 6; }
+ else { i = 1; lan_ch = 7; }
+ ser_ch = 1;
+ }
+ }
+ }
+ if ((gcm_ch != 0) && (lan_ch_parm == 0xff)) {
+ /* Has a GCM, and user didn't specify -L */
+ /* Need this to avoid picking channel 3, the IMM GCM channel. */
+ lan_ch = 1; /*default BMC LAN channel*/
+ // i = 1; /*default eth1*/
+ }
+ if (fsetifn == 0) {
+ if (lan_ch == gcm_ch) strcpy(ifname,"gcm");
+ else sprintf(ifname,"%s%d",ifpattn,i);
+ }
+ if (fdebug) printf("lan_ch = %d, ifname = %s\n",lan_ch,ifname);
+
+ /* initialize the correct SOL command values */
+ if (fIPMI20 && fSOL20) {
+ setsolcmd = SET_SOL_CONFIG2;
+ getsolcmd = GET_SOL_CONFIG2;
+ sol_bchan = lan_ch;
+ } else {
+ setsolcmd = SET_SOL_CONFIG;
+ getsolcmd = GET_SOL_CONFIG;
+ sol_bchan = 0x00; /*override chan for IPMI 1.5*/
+ }
+
+ memset(SessInfo,0,sizeof(SessInfo));
+ ret = GetSessionInfo(SessInfo,sizeof(SessInfo));
+ // rlen = sizeof(SessInfo)); ret = get_session_info(0,0,SessInfo,&rlen);
+ if (fdebug) printf("GetSessionInfo ret=%d, data: %02x %02x %02x %02x \n",
+ ret,SessInfo[0],SessInfo[1],SessInfo[2],SessInfo[3]);
+ if (!freadonly && fipmilan) { /* setting LAN params, and using IPMI LAN */
+ if (SessInfo[2] > 1) { /* another session is active also */
+ printf("Another session is also active, cannot change IPMI LAN settings now.\n");
+ ret = ERR_NOT_ALLOWED;
+ goto do_exit;
+ }
+ }
+
+ /* set the lan_user appropriately */
+ if (freadonly)
+ {
+ if (!fIPMI10) {
+ printf("%c## %s, GetPefEntry ...\n",bcomment,progname);
+ for (idx = 1; idx <= pefmax; idx++)
+ {
+ ret = GetPefEntry( 0x06, (ushort)idx, &PefRecord);
+ if (ret == 0) { // Show the PEF record
+ pc = (uchar *)&PefRecord;
+ sz = 21; // sizeof(PEF_RECORD) = 21
+ printf("%c PefParam(%d): %s\n",bcomment,idx,PefDesc(idx,pc[7]));
+ fprintf(fd_bmc,"PEFParam %d,%02d%c",6,idx,bdelim);
+ for (i = 0; i < sz; i++) fprintf(fd_bmc," %02x",pc[i]);
+ fprintf(fd_bmc,"\n");
+ } else {
+ char *pstr;
+ if (ret > 0) pstr = decode_cc(0,(uchar)ret);
+ else pstr = "";
+ printf("%c GetPefEntry(%d): ret = %d %s\n",bcomment,idx,ret,pstr);
+ if (ret == 0xC1) {
+ fpefok = 0;
+ ndest = 0;
+ break;
+ }
+ }
+ }
+ if (fpefok) {
+ ret = GetPefEntry(0x01, 0,(PEF_RECORD *)&LanRecord);
+ if (ret == 0) {
+ fprintf(fd_bmc,"PEFParam %d%c %02x\n",1,bdelim,LanRecord[0]);
+ }
+ ret = GetPefEntry(0x02, 0,(PEF_RECORD *)&LanRecord);
+ if (ret == 0) {
+ fprintf(fd_bmc,"PEFParam %d%c %02x\n",2,bdelim,LanRecord[0]);
+ }
+ ret = GetPefEntry(0x03, 0,(PEF_RECORD *)&LanRecord);
+ if (ret == 0)
+ fprintf(fd_bmc,"PEFParam %d%c %02x\n", 3,bdelim,LanRecord[0]);
+ if (!fmBMC) {
+ ret = GetPefEntry(0x04, 0,(PEF_RECORD *)&LanRecord);
+ if (ret == 0)
+ fprintf(fd_bmc,"PEFParam %d%c %02x\n",4,bdelim,LanRecord[0]);
+ /* fmBMC gets cc=0x80 here */
+ }
+ /* note that ndest should be read from lan param 17 below. */
+ for (i = 1; i <= ndest; i++)
+ {
+ ret = GetPefEntry(0x09, (ushort)i,(PEF_RECORD *)&LanRecord);
+ if (ret == 0) {
+ fprintf(fd_bmc,"PEFParam %d,%d%c %02x %02x %02x %02x \n",9,i,bdelim,
+ LanRecord[0], LanRecord[1],LanRecord[2], LanRecord[3]);
+ }
+ } /*endfor ndest*/
+ } /*endif fpefok*/
+ } /*endif not fIPMI10*/
+
+ for (chan = lan_ch; chan < MAXCHAN; chan++ )
+ {
+ if (chan_type[chan] != 4) continue; /*chan != LAN, skip it*/
+ lan_ch = chan;
+ printf("%c## %s, GetLanEntry for channel %d ...\n",bcomment,progname,lan_ch);
+ idest = 1;
+ for (idx = 0; idx < NLAN; idx++)
+ {
+ int ival;
+ if (idx == 8 || idx == 9) continue; /* not implemented */
+ ival = lanparams[idx].cmd;
+ if (ival >= 96 && ival <= 98) continue; /* not implemented */
+ if (ival >= 102 && ival <= 108) { /*custom IPv6 parameters*/
+ if (fipv6 == 0) continue; /*skip these*/
+ }
+ if (ival == 194 && vend_id == VENDOR_KONTRON) { /*oem hostname parm*/
+ lanparams[idx].sz = 36;
+ strcpy(lanparams[idx].desc,"IPMI Hostname");
+ } else if (ival >= 192 && ival <= 194) { /*custom DHCP parameters*/
+ if (vend_id != VENDOR_INTEL) continue;
+ if (fmBMC || fiBMC || fRomley || fcanonical) continue; /*skip*/
+ }
+ /* VLAN params 20-25, fIPMI20 only*/
+ if (ival >= 20 && ival <= 25) { if (!fIPMI20) continue; }
+ if (ival == 11) { /*grat arp interval*/
+ if (vend_id == VENDOR_SUPERMICROX) continue;
+ if (vend_id == VENDOR_SUPERMICRO) continue;
+ }
+ if (ival == 14 || ival == 15) { /*secondary gateway is optional*/
+ if (vend_id == VENDOR_KONTRON) continue;
+ }
+ if (ival == 201) { /*Get Channel Access*/
+ ret = ShowChanAcc(lan_ch);
+ } else {
+ if (ival == 18 || ival == 19) { /*dest params*/
+ if (ndest == 0) continue; /*skip if none*/
+ bset = (uchar)idest; /* dest id = 1 thru n */
+ } else bset = 0;
+ ret = GetLanEntry((uchar)ival, bset, LanRecord);
+ }
+ if (ret == 0) { // Show the LAN record
+ pc = (uchar *)&LanRecord;
+ sz = lanparams[idx].sz;
+ if (ival == 201) ; /* ShowChanAcc(lan_ch) above */
+ else {
+ fprintf(fd_bmc,"LanParam %d,%d,%d%c ",lan_ch,ival,bset,bdelim);
+ for (i = 0; i < sz; i++) fprintf(fd_bmc," %02x",pc[i]);
+ fprintf(fd_bmc,"\n");
+ if (ival == 3)
+ printf("%c LanParam(%d,%d,%d) IP address: %d.%d.%d.%d\n",
+ bcomment, lan_ch,ival,bset,
+ pc[0], pc[1], pc[2], pc[3]);
+ }
+
+ if (ival == 1) {
+ authmask = pc[0]; /* auth type support mask */
+ /* if (fmBMC) authmask is usually 0x15, else 0x14 */
+ } else if (ival == 3) {
+ if (IpIsValid(pc)) memcpy(bmcmyip,pc,4);
+ } else if (ival == 5) {
+ if (MacIsValid(pc)) memcpy(bmcmymac,pc,MAC_LEN);
+ } else if (ival == 17) { /* num dest */
+ ndest = pc[0]; /* save the number of destinations */
+ } else if (ival == 19) { /* dest addr */
+ if (IpIsValid(&pc[3])) memcpy(bmcdestip,&pc[3],4);
+ }
+
+ if (ival == 18 || ival == 19) {
+ if (idest < ndest) {
+ idest++;
+ idx--; /* repeat this param*/
+ } else idest = 1;
+ }
+ } else { /* ret != 0 */
+ if (ival >= 20 && ival <= 25) ;
+ else
+ printf("%c GetLanEntry(%d,%d,%d), ret = %d\n",bcomment,lan_ch,ival,bset,ret);
+ if (ival == 17) ndest = 0; /*error getting num dest*/
+ }
+ } /*end for NLAN*/
+ if (!fIPMI10) { /* Get SOL params */
+ ret = GetSerialOverLan(lan_ch,0,0);
+ if (ret != 0) printf("%c GetSOL error %d\n",bcomment,ret);
+ }
+ for (idx = 1; idx <= nusers; idx++)
+ GetUser(idx);
+ if (lan_ch_parm != 0xff) chan = MAXCHAN;
+ } /*end-for chan*/
+
+ printf("%c## %s, GetSerEntry for channel %d ...\n",bcomment,progname,ser_ch);
+ if (fmBMC || (ser_ch == 0)) { /* mBMC doesn't support serial */
+ printf("%cNo serial channel support on this platform\n",
+ bcomment);
+ } else {
+ idest = 1;
+ for (idx = 0; idx < NSER; idx++) {
+ int ival;
+ // if (idx == 9) continue; /* not implemented */
+ ival = serparams[idx].cmd;
+ if (vend_id == VENDOR_SUPERMICRO && ival == 8) continue;
+ if (ival == 201) {
+ j = ShowChanAcc(ser_ch);
+ } else {
+ if (ival == 17 || ival == 19 || ival == 21 || ival == 23)
+ bset = (uchar)idest;
+ else bset = 0; /*default*/
+ ret = GetSerEntry((uchar)ival, bset, LanRecord);
+ if (ret == 0) { // Show the SER record
+ pc = (uchar *)&LanRecord;
+ sz = serparams[idx].sz;
+ fprintf(fd_bmc,"SerialParam %d,%d,%d%c",
+ ser_ch,ival,bset,bdelim);
+ for (i = 0; i < sz; i++)
+ fprintf(fd_bmc," %02x",pc[i]); /* show in hex */
+ fprintf(fd_bmc,"\n");
+ if (ival == 16) ndest = pc[0];
+ } else { /*ret != 0, error*/
+ char *pstr;
+ char *tag;
+ if (SerialIsOptional(ival)) tag = "Optional";
+ else tag = "";
+ if (ret > 0) pstr = decode_cc(0,ret);
+ else pstr = "";
+ printf("%c GetSerEntry(%d,%d): %s ret = %d %s\n",
+ bcomment,ser_ch,ival,tag,ret,pstr);
+ if (ival == 16) ndest = 0;
+ if (ret == 0xC1) {
+ ret = 0;
+ break; /*not supported, exit for loop*/
+ }
+ }
+ }
+ if (ival == 17 || ival == 19 || ival == 21 || ival == 23) {
+ if (idest < ndest) {
+ idest++;
+ idx--; /* repeat this param*/
+ } else idest = 1;
+ }
+ } /*end for NSER*/
+ lan_ch_sav = lan_ch;
+ lan_ch = ser_ch; /* use ser_ch for User functions now */
+ for (idx = 1; idx <= nusers; idx++)
+ GetUser(idx);
+ lan_ch = lan_ch_sav;
+ } /*endif serial*/
+
+ printf("%c## %s, GetSystemParams ...\n",bcomment,progname);
+ for (idx = 0; idx < NSYS; idx++) { /*Get System Params*/
+ switch(idx) {
+ case 0: j = CHAS_RESTORE; bset = 0; break;
+ case 1: j = SYS_INFO; bset = 1; break;
+ case 2: j = SYS_INFO; bset = 2; break;
+ case 3: j = SYS_INFO; bset = 3; break;
+ case 4: j = SYS_INFO; bset = 4; break;
+ case 5:
+ default: j = LAN_FAILOVER; bset = 0; break;
+ }
+ fignore_err = 0;
+ pc = (uchar *)&LanRecord;
+ switch(j) {
+ case CHAS_RESTORE: /* Chassis Status, Power Restore Policy */
+ sz = 0;
+ rlen = sizeof(rData);
+ ret = ipmi_cmdraw(CHASSIS_STATUS, NETFN_CHAS,
+ BMC_SA,PUBLIC_BUS,BMC_LUN,
+ pc,0,rData,&rlen,&cc,fdebug);
+ if (ret == 0 && cc != 0) ret = cc;
+ if (ret == 0) {
+ sz = rlen;
+ memcpy(pc,&rData,sz); /*should be 3 bytes*/
+ }
+ break;
+ case SYS_INFO: /* System Info */
+ if (! fIPMI20) continue; /*skip if not IPMI 2.0*/
+ rlen = sizeof(LanRecord); /* param from read */
+ ret = get_system_info(bset,LanRecord,&rlen);
+ /* find actual string size (ends at first 0x00) */
+ for (i=0; i<rlen; i++) if (LanRecord[i] == 0) break;
+ if (i < rlen) rlen = i;
+ sz = rlen;
+ fignore_err = 1;
+ break;
+ case LAN_FAILOVER: /* Intel LAN Failover */
+ if (is_romley(vend_id,prod_id))
+ ret = lan_failover_intel(0xFF,&LanRecord[0]);
+ else continue; /*skip if not Intel Romley */
+ sz = 1;
+ fignore_err = 1;
+ break;
+ default: /*do nothing*/
+ sz = 0;
+ ret = LAN_ERR_NOTSUPPORT;
+ break;
+ } /*end switch*/
+ if (ret == 0) {
+ fprintf(fd_bmc,"SystemParam %d,%d%c ",j,bset,bdelim);
+ for (i = 0; i < sz; i++) fprintf(fd_bmc," %02x",pc[i]);
+ fprintf(fd_bmc,"\n");
+ } else {
+ char *pstr;
+ if (ret > 0) pstr = decode_cc(0,ret);
+ else pstr = "";
+ if (fdebug || !fignore_err)
+ printf("%c GetSystemParam(%d,%d): ret = %d %s\n",
+ bcomment,j,bset,ret,pstr);
+ if (fignore_err) ret = 0;
+ }
+ } /*end-for System Params*/
+
+ } /*endif readonly*/
+
+ if (!freadonly) /* Set parameters via Restore */
+ {
+ if (fipmilan) { /* Sets not valid via ipmi_lan if same channel. */
+ printf("\nWarning: Setting LAN %d params while using a LAN channel.\n", lan_ch);
+ }
+ GetUser(1); /*sets num enabled_users */
+
+ /* Set BMC parameters. (restore) */
+ /* read each record from the file */
+ while ( fgets( line, sizeof(line), fd_bmc) != NULL )
+ {
+ ret = parse_line(line, key, value);
+ if (ret != 0) {
+ if (ret == 2) ret = 0; /*just skip comment*/
+ else if (fdebug) printf("parse error on line: %s\n",line);
+ continue;
+ }
+
+ /* get parameters from key */
+ sz = sizeof(bParams);
+ memset(bParams,0,sz);
+ pk = strchr(key,' '); /*skip keyword, to first param*/
+ if (pk == NULL) {
+ pk = &key[0];
+ }
+ for (n=0; n<sz; n++)
+ {
+ pc = strchr(pk,',');
+ if (pc != NULL) {
+ *pc = 0;
+ bParams[n] = atob(pk);
+ pk = (char *)++pc;
+ } else {
+ bParams[n] = atob(pk);
+ break;
+ }
+ }
+ /* n == number of params, usually 3 */
+ chan = bParams[0];
+ idx = bParams[1];
+ bset = bParams[2];
+ /* get data from value */
+ pc = value;
+ sz = strlen_(value);
+ for (j=0,i=0; i<sz; i+=3)
+ LanRecord[j++] = htoi(&pc[i]);
+ if (fdebug) {
+ printf("Record(%d,%d,%d):",chan,idx,bset);
+ for (i=0; i<j; i++) printf(" %02x",LanRecord[i]);
+ printf("\n");
+ }
+
+ if (strncasecmp(key,"LanParam",8) == 0) {
+ if (idx == 0) continue; /*skip Set in progress*/
+ if (idx == 1 || idx == 17) continue; /*read-only params*/
+ if (idx == 5 && fIPMI20) /*BMC MAC address & IPMI 2.0(not shared)*/
+ if (fdomac == 0) continue; /*skip BMC MAC unless -m */
+ if ((idx == 10) && (chan == gcm_ch)) continue; /*skip Lan3 arp*/
+ if ((vend_id == VENDOR_PEPPERCON) && (idx == 7)) continue;
+ if ((idx == 18 || idx == 19) && (ndest == 0)) continue;
+ if (idx >= 22 && idx <= 24) continue; /*read-only Cipher*/
+ else if (idx >= 20 && idx <= 25) { /*VLAN*/
+ if (!fIPMI20) continue;
+ }
+ if (idx == 18) j--; /*one less byte for Set than from Get*/
+ lan_ch = chan;
+ if (idx == 3) { /* 3 = IP address */
+ uchar bdata[2];
+ bdata[0] = 0x00; /*disable grat arp while setting IP*/
+ ret = SetLanEntry(10, &bdata[0], 1);
+ if (fdebug) printf("SetLanEntry(%d,10,0), ret = %d\n",chan,ret);
+ WaitForSetComplete(4); /*wait if it is a slow MC */
+ bdata[0] = SRC_STATIC; /*set src to static before setting IP*/
+ ret = SetLanEntry(4, &bdata[0], 1);
+ if (fdebug) printf("SetLanEntry(%d,4,0), ret = %d\n",chan,ret);
+ WaitForSetComplete(4); /*wait if it is a slow MC */
+ }
+ else if ((idx == 6) || (idx == 12)) WaitForSetComplete(4);
+ ret = SetLanEntry(idx, LanRecord, j);
+ if ((ret != 0) && (idx >= 20 && idx <= 25)) ; /*VLAN optional*/
+ else {
+ printf("SetLanEntry(%d,%d), ret = %d\n",chan,idx,ret);
+ if (ret != 0) { nerrs++; lasterr = ret; }
+ else ngood++;
+ }
+
+ } else if (strncasecmp(key,"PEFParam",8) == 0) {
+ if (fpefok == 0) continue;
+ idx = bParams[0];
+ bset = bParams[1];
+ if (idx == 6) { /*PEF table rules*/
+ pPefRecord = (PEF_RECORD *)&LanRecord[0];
+ if (pPefRecord->fconfig == 0xC0) {
+ pPefRecord->fconfig = 0x80; /* enabled, software */
+ ret = SetPefEntry(pPefRecord);
+ if (fdebug)
+ printf("SetPefEntry(%d,%d/80) ret = %d\n",idx,bset,ret);
+ pPefRecord->fconfig = 0xC0;
+ }
+ ret = SetPefEntry(pPefRecord);
+ printf("SetPefEntry(%d,%d) ret = %d\n",idx,bset,ret);
+ if (ret != 0) { nerrs++; lasterr = ret; }
+ else ngood++;
+ } else {
+ pc = (uchar *)&PefRecord;
+ pc[0] = idx;
+ for (i=0; i<j; i++)
+ pc[i+1] = LanRecord[i];
+ rlen = sizeof(rData);
+ ret = ipmi_cmd(SET_PEF_CONFIG, pc,j+1, rData,&rlen, &cc,fdebug);
+ if ((ret == 0) && (cc != 0)) ret = cc;
+ if ((idx == 9) && (bset > 1) && (ret != 0)); /*9=PEF Policy*/
+ else {
+ printf("SetPefEntry(%d,%d) ret = %d\n",idx,bset,ret);
+ if (ret != 0) { nerrs++; lasterr = ret; }
+ else ngood++;
+ }
+ }
+ if (ret == 0xC1) { fpefok = 0; ndest = 0; }
+
+ } else if (strncasecmp(key,"SerialParam",11) == 0) {
+ if (idx == 0) continue; /*skip Set in progress*/
+ if (idx == 1 || idx == 16) continue; /*read-only param*/
+ if (vend_id == VENDOR_PEPPERCON) {
+ if ((idx >= 3) && (idx <= 6)) continue;
+ }
+ if ((vend_id == VENDOR_SUPERMICROX) ||
+ (vend_id == VENDOR_SUPERMICRO)) {
+ if (idx == 3) continue;
+ if ((idx >= 6) && (idx <= 8)) continue;
+ if (idx == 29) continue;
+ }
+ if (fmBMC || (ser_ch == 0)) continue; /*doesn't support serial*/
+ ser_ch = chan;
+ ret = SetSerEntry(idx, LanRecord, j);
+ if ((ret != 0) && SerialIsOptional(idx)) ; /*ignore errors if opt*/
+ else {
+ printf("SetSerEntry(%d,%d,%d), ret = %d\n",chan,idx,bset,ret);
+ if (ret != 0) { nerrs++; lasterr = ret; }
+ else ngood++;
+ }
+ } else if (strncasecmp(key,"ChannelAccess",13) == 0) {
+ if (((vend_id == VENDOR_SUPERMICROX) ||
+ (vend_id == VENDOR_SUPERMICRO)) && chan == 3) ; /*skip serial*/
+ else {
+ ret = SetChanAcc(chan, 0x80, LanRecord[0], LanRecord[1]);
+ if (fdebug) printf("SetChanAcc(%d/active), ret = %d\n",chan,ret);
+ ret = SetChanAcc(chan, 0x40, LanRecord[0], LanRecord[1]);
+ printf("SetChanAcc(%d), ret = %d\n",chan,ret);
+ if (ret != 0) { nerrs++; lasterr = ret; }
+ else ngood++;
+ }
+
+ } else if (strncasecmp(key,"UserName",8) == 0) {
+ if (fchan2wart && (lan_ch == 2)) continue;
+ idx = bParams[0];
+ if (idx <= 1) ; /*skip if anonymous user 1*/
+ else if (idx == 2 && vend_id == VENDOR_SUPERMICROX) ; /*skip user2*/
+ else if (idx == 2 && vend_id == VENDOR_SUPERMICRO) ; /*skip user2*/
+ else {
+ pc = (uchar *)&PefRecord;
+ pc[0] = idx; /*user num*/
+ memcpy(&pc[1],&LanRecord[0],16);
+ rlen = sizeof(rData);
+ ret = ipmi_cmd(SET_USER_NAME,pc,17, rData,&rlen, &cc,fdebug);
+ if (ret == 0 && cc != 0) ret = cc;
+ if (ret == 0xCC) ; /*SetUserName matching previous gives this*/
+ else {
+ printf("SetUserName(%d) ret = %d\n",idx,ret);
+ if (ret != 0) { nerrs++; lasterr = ret; }
+ else ngood++;
+ }
+ }
+ if (fpassword) {
+ pc = (uchar *)&PefRecord;
+ pc[0] = idx; /*user num*/
+ pc[1] = 0x02; /*set password*/
+ memset(&pc[2],0, PSW_LEN);
+ strcpy(&pc[2],passwordData);
+ rlen = sizeof(rData);
+ ret = ipmi_cmd(SET_USER_PASSWORD,pc,2+PSW_LEN,rData,&rlen,
+ &cc,fdebug);
+ printf("SetUserPassword(%d) ret = %d\n",idx,ret);
+ if (ret != 0) { nerrs++; lasterr = ret; }
+ else ngood++;
+ }
+ } else if (strncasecmp(key,"UserPassword",12) == 0) {
+ if (fchan2wart && (lan_ch == 2)) continue;
+ idx = bParams[0];
+ pc = (uchar *)&PefRecord;
+ pc[0] = idx; /*user num*/
+ pc[1] = 0x02; /*set password*/
+ memset(&pc[2],0,PSW_LEN);
+ strcpy(&pc[2],passwordData);
+ rlen = sizeof(rData);
+ ret = ipmi_cmd(SET_USER_PASSWORD,pc,2+PSW_LEN,rData,&rlen,
+ &cc,fdebug);
+ printf("SetUserPassword(%d) ret = %d\n",idx,ret);
+ if (ret != 0) { nerrs++; lasterr = ret; }
+ else ngood++;
+ } else if (strncasecmp(key,"UserAccess",10) == 0) {
+ if ((idx > enabled_users) && ((LanRecord[3] & 0x10) == 0)) continue;
+ if (vend_id == VENDOR_KONTRON) {
+ if (idx == 1) continue;
+ if (idx > enabled_users) continue;
+ }
+ if (ipmi_reserved_user(vend_id,idx) == 1) continue;
+ if (fchan2wart && (lan_ch == 2)) continue;
+ pc = (uchar *)&PefRecord;;
+ pc[0] = 0x80 | (LanRecord[3] & 0x70) | chan; /*User Channel Access*/
+ pc[1] = idx; /*user id*/
+ pc[2] = (LanRecord[3] & 0x0F); /*User Privilege (Admin,User,Oper)*/
+ pc[3] = 0x00; /* User Session Limit, 0=not limited*/
+ rlen = sizeof(rData);
+ ret = ipmi_cmd(SET_USER_ACCESS,pc,4, rData,&rlen, &cc,fdebug);
+ if (ret == 0 && cc != 0) ret = cc;
+ if (ret != 0xCC) { /*if invalid user, ignore errors*/
+ printf("SetUserAccess (%x %x %x %x) ret = %d\n",
+ pc[0],pc[1],pc[2],pc[3],ret);
+ if (ret != 0) { nerrs++; lasterr = ret; }
+ else ngood++;
+ }
+ if ((LanRecord[3] & 0x0f) != 0x0F) { /*not NoAccess, enable user*/
+ if (idx > last_user_enable) last_user_enable = idx;
+ pc[0] = idx; /*user number, 1=null_user */
+ pc[1] = 0x01; /*enable user*/
+ rlen = sizeof(rData);
+ ret = ipmi_cmd(SET_USER_PASSWORD,pc,2, rData,&rlen, &cc,fdebug);
+ if (ret == 0 && cc != 0) ret = cc;
+ printf("SetUserEnable (%x %x) ret = %d\n",pc[0],pc[1],ret);
+ if (ret != 0) { nerrs++; lasterr = ret; }
+ else ngood++;
+ }
+ } else if (strncasecmp(key,"SOLParam",8) == 0) {
+ if (fchan2wart && (chan == 2)) continue;
+ pc = (uchar *)&PefRecord;;
+ pc[0] = chan;
+ pc[1] = idx; /*sol parameter number*/
+ memcpy(&pc[2],&LanRecord,j);
+ rlen = sizeof(rData);
+ ret = ipmi_cmd(setsolcmd, pc, j+2, rData,&rlen, &cc,fdebug);
+ if (ret == 0 && cc != 0) ret = cc;
+ printf("SetSOLParam (%d,%d) ret = %d\n",chan,idx,ret);
+ if (ret != 0) { nerrs++; lasterr = ret; }
+ else ngood++;
+
+ } else if (strncasecmp(key,"SOLPayloadSupport",17) == 0) {
+ ; /* Nothing to do, this is a read-only parameter */
+
+ } else if (strncasecmp(key,"SOLPayloadAccess",16) == 0) {
+ if (fIPMI20) {
+ if (ipmi_reserved_user(vend_id,idx) == 1) continue;
+ pc = (uchar *)&PefRecord;;
+ pc[0] = chan;
+ pc[1] = idx; // lan_user
+ memcpy(&pc[2],&LanRecord,j);
+ rlen = sizeof(rData);
+ ret = ipmi_cmdraw(SET_PAYLOAD_ACCESS,NETFN_APP,
+ BMC_SA,PUBLIC_BUS,BMC_LUN,
+ pc,j+2,rData,&rlen,&cc,fdebug);
+ if (ret == 0 && cc != 0) ret = cc;
+ printf("SetSOLPayloadAccess (%d,%d) ret = %d\n",
+ chan,idx,ret);
+ if (ret != 0) { nerrs++; lasterr = ret; }
+ else ngood++;
+ }
+ } else if (strncasecmp(key,"SystemParam",11) == 0) {
+ idx = bParams[0];
+ bset = bParams[1];
+ switch(idx) {
+ case CHAS_RESTORE: /* Chassis Power Restore Policy*/
+ if (vend_id == VENDOR_KONTRON) continue; /*N/A, cannot set it*/
+ pc = (uchar *)&PefRecord;;
+ i = (LanRecord[0] & 0x60); /*restore policy bits*/
+ if (i & 0x20) pc[0] = 0x01; /*last_state*/
+ else if (i & 0x40) pc[0] = 0x02; /*turn_on*/
+ else pc[0] = 0x00; /*stay_off*/
+ rlen = sizeof(rData);
+ ret = ipmi_cmdraw(0x06 , NETFN_CHAS,
+ BMC_SA,PUBLIC_BUS,BMC_LUN,
+ pc,1,rData,&rlen,&cc,fdebug);
+ if (ret == 0 && cc != 0) ret = cc;
+ break;
+ case SYS_INFO: /* System Info */
+ if (! fIPMI20) continue; /*skip if not IPMI 2.0*/
+ /* j = #bytes read into LanRecord */
+ ret = set_system_info(bset,LanRecord,j);
+ break;
+ case LAN_FAILOVER: /* Intel LAN Failover */
+ if (is_romley(vend_id,prod_id))
+ ret = lan_failover_intel(LanRecord[0],(uchar *)&i);
+ else continue; /*skip if not Intel Romley*/
+ break;
+ default:
+ ret = LAN_ERR_NOTSUPPORT;
+ }
+ printf("SetSystemParam(%d,%d) ret = %d\n",idx,bset,ret);
+ if (ret != 0) { nerrs++; lasterr = ret; }
+ else ngood++;
+ } /*end-else*/
+
+ } /*end-while*/
+
+ /* Disable any users not enabled above */
+ for (i = last_user_enable+1; i < max_users; i++) {
+ pc[0] = (uchar)i; /*user number, 1=null_user */
+ pc[1] = 0x00; /*disable user*/
+ rlen = sizeof(rData);
+ ret = ipmi_cmd(SET_USER_PASSWORD,pc,2, rData,&rlen, &cc,fdebug);
+ if (ret == 0 && cc != 0) ret = cc;
+ printf("SetUserEnable (%x %x) ret = %d\n",pc[0],pc[1],ret);
+ if (ret != 0) { nerrs++; lasterr = ret; }
+ else ngood++;
+ }
+ } /*endif not readonly*/
+
+do_exit:
+ if (fd_bmc != stdout) fclose(fd_bmc);
+ ipmi_close_();
+ if (nerrs > 0) {
+ printf("Warning: %d ok, %d errors occurred, last error = %d\n",ngood,nerrs,lasterr);
+ ret = lasterr;
+ }
+ // show_outcome(progname,ret);
+ return(ret);
+} /* end main()*/
+
+/* end iconfig.c */