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