1 /*
2 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * Redistribution of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * Redistribution in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * Neither the name of Sun Microsystems, Inc. or the names of
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * This software is provided "AS IS," without a warranty of any kind.
20 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
23 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
24 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
25 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
26 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
27 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
28 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
29 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31 */
32
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
40 #include <errno.h>
41 #include <unistd.h>
42 #include <signal.h>
43
44 #include <ipmitool/ipmi.h>
45 #include <ipmitool/ipmi_intf.h>
46 #include <ipmitool/helper.h>
47 #include <ipmitool/log.h>
48 #include <ipmitool/ipmi_lanp.h>
49 #include <ipmitool/ipmi_session.h>
50 #include <ipmitool/ipmi_strings.h>
51 #include <ipmitool/bswap.h>
52
53
54 typedef enum {
55 IPMI_SESSION_REQUEST_CURRENT = 0,
56 IPMI_SESSION_REQUEST_ALL,
57 IPMI_SESSION_REQUEST_BY_ID,
58 IPMI_SESSION_REQUEST_BY_HANDLE
59 } Ipmi_Session_Request_Type;
60
61
62
63
64 /*
65 * print_session_info_csv
66 */
67 static void
print_session_info_csv(const struct get_session_info_rsp * session_info,int data_len)68 print_session_info_csv(const struct get_session_info_rsp * session_info,
69 int data_len)
70 {
71 char buffer[18];
72 uint16_t console_port_tmp;
73
74 printf("%d", session_info->session_handle);
75 printf(",%d", session_info->session_slot_count);
76 printf(",%d", session_info->active_session_count);
77
78 if (data_len == 3)
79 {
80 /* There is no session data here*/
81 printf("\n");
82 return;
83 }
84
85 printf(",%d", session_info->user_id);
86 printf(",%s", val2str(session_info->privilege_level, ipmi_privlvl_vals));
87
88 printf(",%s", session_info->auxiliary_data?
89 "IPMIv2/RMCP+" : "IPMIv1.5");
90
91 printf(",0x%02x", session_info->channel_number);
92
93 if (data_len == 18)
94 {
95 /* We have 802.3 LAN data */
96 printf(",%s",
97 inet_ntop(AF_INET,
98 &(session_info->channel_data.lan_data.console_ip),
99 buffer,
100 16));
101
102 printf(",%02x:%02x:%02x:%02x:%02x:%02x",
103 session_info->channel_data.lan_data.console_mac[0],
104 session_info->channel_data.lan_data.console_mac[1],
105 session_info->channel_data.lan_data.console_mac[2],
106 session_info->channel_data.lan_data.console_mac[3],
107 session_info->channel_data.lan_data.console_mac[4],
108 session_info->channel_data.lan_data.console_mac[5]);
109
110 console_port_tmp = session_info->channel_data.lan_data.console_port;
111 #if WORDS_BIGENDIAN
112 console_port_tmp = BSWAP_16(console_port_tmp);
113 #endif
114 printf(",%d", console_port_tmp);
115 }
116
117
118 else if ((data_len == 12) || (data_len == 14))
119 {
120 /* Channel async serial/modem */
121 printf(",%s",
122 val2str(session_info->channel_data.modem_data.session_channel_activity_type,
123 ipmi_channel_activity_type_vals));
124
125 printf(",%d",
126 session_info->channel_data.modem_data.destination_selector);
127
128 printf(",%s",
129 inet_ntop(AF_INET,
130 &(session_info->channel_data.modem_data.console_ip),
131 buffer,
132 16));
133
134 if (data_len == 14)
135 {
136 /* Connection is PPP */
137 console_port_tmp = session_info->channel_data.lan_data.console_port;
138 #if WORDS_BIGENDIAN
139 console_port_tmp = BSWAP_16(console_port_tmp);
140 #endif
141 printf(",%d", console_port_tmp);
142 }
143 }
144
145 printf("\n");
146 }
147
148
149
150 /*
151 * print_session_info_verbose
152 */
153 static void
print_session_info_verbose(const struct get_session_info_rsp * session_info,int data_len)154 print_session_info_verbose(const struct get_session_info_rsp * session_info,
155 int data_len)
156 {
157 char buffer[18];
158 uint16_t console_port_tmp;
159
160 printf("session handle : %d\n", session_info->session_handle);
161 printf("slot count : %d\n", session_info->session_slot_count);
162 printf("active sessions : %d\n", session_info->active_session_count);
163
164 if (data_len == 3)
165 {
166 /* There is no session data here */
167 printf("\n");
168 return;
169 }
170
171 printf("user id : %d\n", session_info->user_id);
172 printf("privilege level : %s\n",
173 val2str(session_info->privilege_level, ipmi_privlvl_vals));
174
175 printf("session type : %s\n", session_info->auxiliary_data?
176 "IPMIv2/RMCP+" : "IPMIv1.5");
177
178 printf("channel number : 0x%02x\n", session_info->channel_number);
179
180
181 if (data_len == 18)
182 {
183 /* We have 802.3 LAN data */
184 printf("console ip : %s\n",
185 inet_ntop(AF_INET,
186 &(session_info->channel_data.lan_data.console_ip),
187 buffer,
188 16));
189
190 printf("console mac : %02x:%02x:%02x:%02x:%02x:%02x\n",
191 session_info->channel_data.lan_data.console_mac[0],
192 session_info->channel_data.lan_data.console_mac[1],
193 session_info->channel_data.lan_data.console_mac[2],
194 session_info->channel_data.lan_data.console_mac[3],
195 session_info->channel_data.lan_data.console_mac[4],
196 session_info->channel_data.lan_data.console_mac[5]);
197
198 console_port_tmp = session_info->channel_data.lan_data.console_port;
199 #if WORDS_BIGENDIAN
200 console_port_tmp = BSWAP_16(console_port_tmp);
201 #endif
202 printf("console port : %d\n", console_port_tmp);
203 }
204
205
206 else if ((data_len == 12) || (data_len == 14))
207 {
208 /* Channel async serial/modem */
209 printf("Session/Channel Activity Type : %s\n",
210 val2str(session_info->channel_data.modem_data.session_channel_activity_type,
211 ipmi_channel_activity_type_vals));
212
213 printf("Destination selector : %d\n",
214 session_info->channel_data.modem_data.destination_selector);
215
216 printf("console ip : %s\n",
217 inet_ntop(AF_INET,
218 &(session_info->channel_data.modem_data.console_ip),
219 buffer,
220 16));
221
222 if (data_len == 14)
223 {
224 /* Connection is PPP */
225 console_port_tmp = session_info->channel_data.lan_data.console_port;
226 #if WORDS_BIGENDIAN
227 console_port_tmp = BSWAP_16(console_port_tmp);
228 #endif
229 printf("console port : %d\n", console_port_tmp);
230 }
231 }
232
233 printf("\n");
234 }
235
236
print_session_info(const struct get_session_info_rsp * session_info,int data_len)237 static void print_session_info(const struct get_session_info_rsp * session_info,
238 int data_len)
239 {
240 if (csv_output)
241 print_session_info_csv(session_info, data_len);
242 else
243 print_session_info_verbose(session_info, data_len);
244 }
245
246
247 /*
248 * ipmi_get_session_info
249 *
250 * returns 0 on success
251 * -1 on error
252 */
253 int
ipmi_get_session_info(struct ipmi_intf * intf,Ipmi_Session_Request_Type session_request_type,uint32_t id_or_handle)254 ipmi_get_session_info(struct ipmi_intf * intf,
255 Ipmi_Session_Request_Type session_request_type,
256 uint32_t id_or_handle)
257 {
258 int i, retval = 0;
259
260 struct ipmi_rs * rsp;
261 struct ipmi_rq req;
262 uint8_t rqdata[5]; // max length of the variable length request
263 struct get_session_info_rsp session_info;
264
265 memset(&req, 0, sizeof(req));
266 memset(&session_info, 0, sizeof(session_info));
267 req.msg.netfn = IPMI_NETFN_APP; // 0x06
268 req.msg.cmd = IPMI_GET_SESSION_INFO; // 0x3D
269 req.msg.data = rqdata;
270
271 switch (session_request_type)
272 {
273
274 case IPMI_SESSION_REQUEST_CURRENT:
275 case IPMI_SESSION_REQUEST_BY_ID:
276 case IPMI_SESSION_REQUEST_BY_HANDLE:
277 switch (session_request_type)
278 {
279 case IPMI_SESSION_REQUEST_CURRENT:
280 rqdata[0] = 0x00;
281 req.msg.data_len = 1;
282 break;
283 case IPMI_SESSION_REQUEST_BY_ID:
284 rqdata[0] = 0xFF;
285 rqdata[1] = id_or_handle & 0x000000FF;
286 rqdata[2] = (id_or_handle >> 8) & 0x000000FF;
287 rqdata[3] = (id_or_handle >> 16) & 0x000000FF;
288 rqdata[4] = (id_or_handle >> 24) & 0x000000FF;
289 req.msg.data_len = 5;
290 break;
291 case IPMI_SESSION_REQUEST_BY_HANDLE:
292 rqdata[0] = 0xFE;
293 rqdata[1] = (uint8_t)id_or_handle;
294 req.msg.data_len = 2;
295 break;
296 case IPMI_SESSION_REQUEST_ALL:
297 break;
298 }
299
300 rsp = intf->sendrecv(intf, &req);
301 if (rsp == NULL)
302 {
303 lprintf(LOG_ERR, "Get Session Info command failed");
304 retval = -1;
305 }
306 else if (rsp->ccode > 0)
307 {
308 lprintf(LOG_ERR, "Get Session Info command failed: %s",
309 val2str(rsp->ccode, completion_code_vals));
310 retval = -1;
311 }
312
313 if (retval < 0)
314 {
315 if ((session_request_type == IPMI_SESSION_REQUEST_CURRENT) &&
316 (strncmp(intf->name, "lan", 3) != 0))
317 lprintf(LOG_ERR, "It is likely that the channel in use "
318 "does not support sessions");
319 }
320 else
321 {
322 memcpy(&session_info, rsp->data, rsp->data_len);
323 print_session_info(&session_info, rsp->data_len);
324 }
325 break;
326
327 case IPMI_SESSION_REQUEST_ALL:
328 req.msg.data_len = 1;
329 i = 1;
330 do
331 {
332 rqdata[0] = i++;
333 rsp = intf->sendrecv(intf, &req);
334
335 if (rsp == NULL)
336 {
337 lprintf(LOG_ERR, "Get Session Info command failed");
338 retval = -1;
339 break;
340 }
341 else if (rsp->ccode > 0 && rsp->ccode != 0xCC && rsp->ccode != 0xCB)
342 {
343 lprintf(LOG_ERR, "Get Session Info command failed: %s",
344 val2str(rsp->ccode, completion_code_vals));
345 retval = -1;
346 break;
347 }
348 else if (rsp->data_len < 3)
349 {
350 retval = -1;
351 break;
352 }
353
354 memcpy(&session_info, rsp->data, rsp->data_len);
355 print_session_info(&session_info, rsp->data_len);
356
357 } while (i <= session_info.session_slot_count);
358 break;
359 }
360
361 return retval;
362 }
363
364
365
366 static void
printf_session_usage(void)367 printf_session_usage(void)
368 {
369 lprintf(LOG_NOTICE, "Session Commands: info <active | all | id 0xnnnnnnnn | handle 0xnn>");
370 }
371
372
373 int
ipmi_session_main(struct ipmi_intf * intf,int argc,char ** argv)374 ipmi_session_main(struct ipmi_intf * intf, int argc, char ** argv)
375 {
376 int retval = 0;
377
378 if (argc == 0 || strncmp(argv[0], "help", 4) == 0)
379 {
380 printf_session_usage();
381 }
382 else if (strncmp(argv[0], "info", 4) == 0)
383 {
384
385 if ((argc < 2) || strncmp(argv[1], "help", 4) == 0)
386 {
387 printf_session_usage();
388 }
389 else
390 {
391 Ipmi_Session_Request_Type session_request_type = 0;
392 uint32_t id_or_handle = 0;
393
394 if (strncmp(argv[1], "active", 6) == 0)
395 session_request_type = IPMI_SESSION_REQUEST_CURRENT;
396 else if (strncmp(argv[1], "all", 3) == 0)
397 session_request_type = IPMI_SESSION_REQUEST_ALL;
398 else if (strncmp(argv[1], "id", 2) == 0)
399 {
400 if (argc >= 3)
401 {
402 session_request_type = IPMI_SESSION_REQUEST_BY_ID;
403 if (str2uint(argv[2], &id_or_handle) != 0) {
404 lprintf(LOG_ERR, "HEX number expected, but '%s' given.",
405 argv[2]);
406 printf_session_usage();
407 retval = -1;
408 }
409 }
410 else
411 {
412 lprintf(LOG_ERR, "Missing id argument");
413 printf_session_usage();
414 retval = -1;
415 }
416 }
417 else if (strncmp(argv[1], "handle", 6) == 0)
418 {
419 if (argc >= 3)
420 {
421 session_request_type = IPMI_SESSION_REQUEST_BY_HANDLE;
422 if (str2uint(argv[2], &id_or_handle) != 0) {
423 lprintf(LOG_ERR, "HEX number expected, but '%s' given.",
424 argv[2]);
425 printf_session_usage();
426 retval = -1;
427 }
428 }
429 else
430 {
431 lprintf(LOG_ERR, "Missing handle argument");
432 printf_session_usage();
433 retval = -1;
434 }
435 }
436 else
437 {
438 lprintf(LOG_ERR, "Invalid SESSION info parameter: %s", argv[1]);
439 printf_session_usage();
440 retval = -1;
441 }
442
443
444 if (retval == 0)
445 retval = ipmi_get_session_info(intf,
446 session_request_type,
447 id_or_handle);
448 }
449 }
450 else
451 {
452 lprintf(LOG_ERR, "Invalid SESSION command: %s", argv[0]);
453 printf_session_usage();
454 retval = -1;
455 }
456
457 return retval;
458 }
459
460