xref: /openbmc/ipmitool/lib/ipmi_session.c (revision c18ec02f)
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