xref: /openbmc/ipmitool/src/plugins/lanplus/lanplus.c (revision 30becb35)
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 #define _GNU_SOURCE
33 
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <inttypes.h>
37 #include <string.h>
38 #include <sys/time.h>
39 #include <sys/types.h>
40 #include <sys/select.h>
41 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
44 #include <errno.h>
45 #include <unistd.h>
46 #include <netdb.h>
47 #include <time.h>
48 #include <fcntl.h>
49 #include <assert.h>
50 
51 #ifdef HAVE_CONFIG_H
52 # include <config.h>
53 #endif
54 #include <ipmitool/helper.h>
55 #include <ipmitool/log.h>
56 #include <ipmitool/ipmi.h>
57 #include <ipmitool/ipmi_lanp.h>
58 #include <ipmitool/ipmi_channel.h>
59 #include <ipmitool/ipmi_intf.h>
60 #include <ipmitool/ipmi_strings.h>
61 #include <ipmitool/hpm2.h>
62 #include <ipmitool/bswap.h>
63 #include <openssl/rand.h>
64 
65 #include "lanplus.h"
66 #include "lanplus_crypt.h"
67 #include "lanplus_crypt_impl.h"
68 #include "lanplus_dump.h"
69 #include "rmcp.h"
70 #include "asf.h"
71 
72 /*
73  * LAN interface is required to support 45 byte request transactions and
74  * 42 byte response transactions.
75  */
76 #define IPMI_LAN_MAX_REQUEST_SIZE	38	/* 45 - 7 */
77 #define IPMI_LAN_MAX_RESPONSE_SIZE	34	/* 42 - 8 */
78 
79 extern const struct valstr ipmi_rakp_return_codes[];
80 extern const struct valstr ipmi_priv_levels[];
81 extern const struct valstr ipmi_auth_algorithms[];
82 extern const struct valstr ipmi_integrity_algorithms[];
83 extern const struct valstr ipmi_encryption_algorithms[];
84 
85 static struct ipmi_rq_entry * ipmi_req_entries;
86 static struct ipmi_rq_entry * ipmi_req_entries_tail;
87 
88 
89 static int ipmi_lanplus_setup(struct ipmi_intf * intf);
90 static int ipmi_lanplus_keepalive(struct ipmi_intf * intf);
91 static int ipmi_lan_send_packet(struct ipmi_intf * intf, uint8_t * data, int data_len);
92 static struct ipmi_rs * ipmi_lan_recv_packet(struct ipmi_intf * intf);
93 static struct ipmi_rs * ipmi_lan_poll_recv(struct ipmi_intf * intf);
94 static struct ipmi_rs * ipmi_lanplus_send_ipmi_cmd(struct ipmi_intf * intf, struct ipmi_rq * req);
95 static struct ipmi_rs * ipmi_lanplus_send_payload(struct ipmi_intf * intf,
96 												  struct ipmi_v2_payload * payload);
97 static void getIpmiPayloadWireRep(
98 								  struct ipmi_intf       * intf,
99 								  struct ipmi_v2_payload * payload,  /* in  */
100 								  uint8_t  * out,
101 								  struct ipmi_rq * req,
102 								  uint8_t    rq_seq,
103 								  uint8_t curr_seq);
104 static void getSolPayloadWireRep(
105 								  struct ipmi_intf       * intf,
106 								 uint8_t          * msg,
107 								 struct ipmi_v2_payload * payload);
108 static void read_open_session_response(struct ipmi_rs * rsp, int offset);
109 static void read_rakp2_message(struct ipmi_rs * rsp, int offset, uint8_t alg);
110 static void read_rakp4_message(struct ipmi_rs * rsp, int offset, uint8_t alg);
111 static void read_session_data(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s);
112 static void read_session_data_v15(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s);
113 static void read_session_data_v2x(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s);
114 static void read_ipmi_response(struct ipmi_rs * rsp, int * offset);
115 static void read_sol_packet(struct ipmi_rs * rsp, int * offset);
116 static struct ipmi_rs * ipmi_lanplus_recv_sol(struct ipmi_intf * intf);
117 static struct ipmi_rs * ipmi_lanplus_send_sol(
118 											  struct ipmi_intf * intf,
119 											  struct ipmi_v2_payload * payload);
120 static int check_sol_packet_for_new_data(
121 									 struct ipmi_intf * intf,
122 									 struct ipmi_rs *rsp);
123 static void ack_sol_packet(
124 							struct ipmi_intf * intf,
125 							struct ipmi_rs * rsp);
126 static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size);
127 static void ipmi_lanp_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size);
128 
129 static uint8_t bridgePossible = 0;
130 
131 struct ipmi_intf ipmi_lanplus_intf = {
132 	.name = "lanplus",
133 	.desc = "IPMI v2.0 RMCP+ LAN Interface",
134 	.setup = ipmi_lanplus_setup,
135 	.open = ipmi_lanplus_open,
136 	.close = ipmi_lanplus_close,
137 	.sendrecv = ipmi_lanplus_send_ipmi_cmd,
138 	.recv_sol = ipmi_lanplus_recv_sol,
139 	.send_sol = ipmi_lanplus_send_sol,
140 	.keepalive = ipmi_lanplus_keepalive,
141 	.set_max_request_data_size = ipmi_lanp_set_max_rq_data_size,
142 	.set_max_response_data_size = ipmi_lanp_set_max_rp_data_size,
143 	.target_addr = IPMI_BMC_SLAVE_ADDR,
144 };
145 
146 
147 extern int verbose;
148 
149 
150 
151 /*
152  * lanplus_get_requested_ciphers
153  *
154  * Set the authentication, integrity and encryption algorithms based
155  * on the cipher suite ID.  See table 22-19 in the IPMIv2 spec for the
156  * source of this information.
157  *
158  * param cipher_suite_id [in]
159  * param auth_alg        [out]
160  * param integrity_alg   [out]
161  * param crypt_alg       [out]
162  *
163  * returns 0 on success
164  *         1 on failure
165  */
lanplus_get_requested_ciphers(int cipher_suite_id,uint8_t * auth_alg,uint8_t * integrity_alg,uint8_t * crypt_alg)166 int lanplus_get_requested_ciphers(int       cipher_suite_id,
167 								  uint8_t * auth_alg,
168 								  uint8_t * integrity_alg,
169 								  uint8_t * crypt_alg)
170 {
171 	if ((cipher_suite_id < 0) || (cipher_suite_id > 14))
172 		return 1;
173 
174 		/* See table 22-19 for the source of the statement */
175 	switch (cipher_suite_id)
176 	{
177 	case 0:
178 		*auth_alg      = IPMI_AUTH_RAKP_NONE;
179 		*integrity_alg = IPMI_INTEGRITY_NONE;
180 		*crypt_alg     = IPMI_CRYPT_NONE;
181 		break;
182 	case 1:
183 		*auth_alg      = IPMI_AUTH_RAKP_HMAC_SHA1;
184 		*integrity_alg = IPMI_INTEGRITY_NONE;
185 		*crypt_alg     = IPMI_CRYPT_NONE;
186 		break;
187 	case 2:
188 		*auth_alg      = IPMI_AUTH_RAKP_HMAC_SHA1;
189 		*integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
190 		*crypt_alg     = IPMI_CRYPT_NONE;
191 		break;
192 	case 3:
193 		*auth_alg      = IPMI_AUTH_RAKP_HMAC_SHA1;
194 		*integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
195 		*crypt_alg     = IPMI_CRYPT_AES_CBC_128;
196 		break;
197 	case 4:
198 		*auth_alg      = IPMI_AUTH_RAKP_HMAC_SHA1;
199 		*integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
200 		*crypt_alg     = IPMI_CRYPT_XRC4_128;
201 		break;
202 	case 5:
203 		*auth_alg      = IPMI_AUTH_RAKP_HMAC_SHA1;
204 		*integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
205 		*crypt_alg     = IPMI_CRYPT_XRC4_40;
206 		break;
207 	case 6:
208 		*auth_alg      = IPMI_AUTH_RAKP_HMAC_MD5;
209 		*integrity_alg = IPMI_INTEGRITY_NONE;
210 		*crypt_alg     = IPMI_CRYPT_NONE;
211 		break;
212 	case 7:
213 		*auth_alg      = IPMI_AUTH_RAKP_HMAC_MD5;
214 		*integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
215 		*crypt_alg     = IPMI_CRYPT_NONE;
216 		break;
217 	case 8:
218 		*auth_alg      = IPMI_AUTH_RAKP_HMAC_MD5;
219 		*integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
220 		*crypt_alg     = IPMI_CRYPT_AES_CBC_128;
221 		break;
222 	case 9:
223 		*auth_alg      = IPMI_AUTH_RAKP_HMAC_MD5;
224 		*integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
225 		*crypt_alg     = IPMI_CRYPT_XRC4_128;
226 		break;
227 	case 10:
228 		*auth_alg      = IPMI_AUTH_RAKP_HMAC_MD5;
229 		*integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
230 		*crypt_alg     = IPMI_CRYPT_XRC4_40;
231 		break;
232 	case 11:
233 		*auth_alg      = IPMI_AUTH_RAKP_HMAC_MD5;
234 		*integrity_alg = IPMI_INTEGRITY_MD5_128;
235 		*crypt_alg     = IPMI_CRYPT_NONE;
236 		break;
237 	case 12:
238 		*auth_alg      = IPMI_AUTH_RAKP_HMAC_MD5;
239 		*integrity_alg = IPMI_INTEGRITY_MD5_128;
240 		*crypt_alg     = IPMI_CRYPT_AES_CBC_128;
241 		break;
242 	case 13:
243 		*auth_alg      = IPMI_AUTH_RAKP_HMAC_MD5;
244 		*integrity_alg = IPMI_INTEGRITY_MD5_128;
245 		*crypt_alg     = IPMI_CRYPT_XRC4_128;
246 		break;
247 	case 14:
248 		*auth_alg      = IPMI_AUTH_RAKP_HMAC_MD5;
249 		*integrity_alg = IPMI_INTEGRITY_MD5_128;
250 		*crypt_alg     = IPMI_CRYPT_XRC4_40;
251 		break;
252 	}
253 
254 	return 0;
255 }
256 
257 
258 
259 /*
260  * Reverse the order of arbitrarily long strings of bytes
261  */
lanplus_swap(uint8_t * buffer,int length)262 void lanplus_swap(
263 				  uint8_t * buffer,
264 						int             length)
265 {
266 	int i;
267 	uint8_t temp;
268 
269 	for (i =0; i < length/2; ++i)
270 	{
271 		temp = buffer[i];
272 		buffer[i] = buffer[length - 1 - i];
273 		buffer[length - 1 - i] = temp;
274 	}
275 }
276 
277 
278 
279 static const struct valstr plus_payload_types_vals[] = {
280 	 { IPMI_PAYLOAD_TYPE_IPMI,              "IPMI (0)" },	// IPMI Message
281 	 { IPMI_PAYLOAD_TYPE_SOL,               "SOL  (1)" },	// SOL (Serial over LAN)
282 	 { IPMI_PAYLOAD_TYPE_OEM,               "OEM  (2)" },	// OEM Explicid
283 
284 	 { IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST, "OpenSession Req (0x10)" },
285 	 { IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE,"OpenSession Resp (0x11)" },
286 	 { IPMI_PAYLOAD_TYPE_RAKP_1,            "RAKP1 (0x12)" },
287 	 { IPMI_PAYLOAD_TYPE_RAKP_2,            "RAKP2 (0x13)" },
288 	 { IPMI_PAYLOAD_TYPE_RAKP_3,            "RAKP3 (0x14)" },
289 	 { IPMI_PAYLOAD_TYPE_RAKP_4,            "RAKP4 (0x15)" },
290 	{ 0x00, NULL },
291 };
292 
293 
294 static struct ipmi_rq_entry *
ipmi_req_add_entry(struct ipmi_intf * intf,struct ipmi_rq * req,uint8_t req_seq)295 ipmi_req_add_entry(struct ipmi_intf * intf, struct ipmi_rq * req, uint8_t req_seq)
296 {
297 	struct ipmi_rq_entry * e;
298 
299 	e = malloc(sizeof(struct ipmi_rq_entry));
300 	if (e == NULL) {
301 		lprintf(LOG_ERR, "ipmitool: malloc failure");
302 		return NULL;
303 	}
304 
305 	memset(e, 0, sizeof(struct ipmi_rq_entry));
306 	memcpy(&e->req, req, sizeof(struct ipmi_rq));
307 
308 	e->intf = intf;
309 	e->rq_seq = req_seq;
310 
311 	if (ipmi_req_entries == NULL)
312 		ipmi_req_entries = e;
313 	else
314 		ipmi_req_entries_tail->next = e;
315 
316 	ipmi_req_entries_tail = e;
317 	lprintf(LOG_DEBUG+3, "added list entry seq=0x%02x cmd=0x%02x",
318 		e->rq_seq, e->req.msg.cmd);
319 	return e;
320 }
321 
322 
323 static struct ipmi_rq_entry *
ipmi_req_lookup_entry(uint8_t seq,uint8_t cmd)324 ipmi_req_lookup_entry(uint8_t seq, uint8_t cmd)
325 {
326 	struct ipmi_rq_entry * e = ipmi_req_entries;
327 
328 	while (e && (e->rq_seq != seq || e->req.msg.cmd != cmd)) {
329 		if (e == e->next)
330 			return NULL;
331 		e = e->next;
332 	}
333 	return e;
334 }
335 
336 static void
ipmi_req_remove_entry(uint8_t seq,uint8_t cmd)337 ipmi_req_remove_entry(uint8_t seq, uint8_t cmd)
338 {
339 	struct ipmi_rq_entry * p, * e, * saved_next_entry;
340 
341 	e = p = ipmi_req_entries;
342 
343 	while (e && (e->rq_seq != seq || e->req.msg.cmd != cmd)) {
344 		p = e;
345 		e = e->next;
346 	}
347 	if (e) {
348 		lprintf(LOG_DEBUG+3, "removed list entry seq=0x%02x cmd=0x%02x",
349 			seq, cmd);
350 		saved_next_entry = e->next;
351 		p->next = (p->next == e->next) ? NULL : e->next;
352 		/* If entry being removed is first in list, fix up list head */
353 		if (ipmi_req_entries == e) {
354 			if (ipmi_req_entries != p)
355 				ipmi_req_entries = p;
356 			else
357 				ipmi_req_entries = saved_next_entry;
358 		}
359 		/* If entry being removed is last in list, fix up list tail */
360 		if (ipmi_req_entries_tail == e) {
361 			if (ipmi_req_entries_tail != p)
362 				ipmi_req_entries_tail = p;
363 			else
364 				ipmi_req_entries_tail = NULL;
365 		}
366 
367 		if (e->msg_data) {
368 			free(e->msg_data);
369 			e->msg_data = NULL;
370 		}
371 		free(e);
372 		e = NULL;
373 	}
374 }
375 
376 static void
ipmi_req_clear_entries(void)377 ipmi_req_clear_entries(void)
378 {
379 	struct ipmi_rq_entry * p, * e;
380 
381 	e = ipmi_req_entries;
382 	while (e) {
383 		lprintf(LOG_DEBUG+3, "cleared list entry seq=0x%02x cmd=0x%02x",
384 			e->rq_seq, e->req.msg.cmd);
385 		p = e->next;
386 		free(e);
387 		e = p;
388 	}
389 
390 	ipmi_req_entries = NULL;
391 	ipmi_req_entries_tail = NULL;
392 }
393 
394 
395 int
ipmi_lan_send_packet(struct ipmi_intf * intf,uint8_t * data,int data_len)396 ipmi_lan_send_packet(
397 					 struct ipmi_intf * intf,
398 					 uint8_t * data, int
399 					 data_len)
400 {
401 	if (verbose >= 5)
402 		printbuf(data, data_len, ">> sending packet");
403 
404 	return send(intf->fd, data, data_len, 0);
405 }
406 
407 
408 
409 struct ipmi_rs *
ipmi_lan_recv_packet(struct ipmi_intf * intf)410 ipmi_lan_recv_packet(struct ipmi_intf * intf)
411 {
412 	static struct ipmi_rs rsp;
413 	fd_set read_set, err_set;
414 	struct timeval tmout;
415 	int ret;
416 
417 	FD_ZERO(&read_set);
418 	FD_SET(intf->fd, &read_set);
419 
420 	FD_ZERO(&err_set);
421 	FD_SET(intf->fd, &err_set);
422 
423 	tmout.tv_sec = intf->session->timeout;
424 	tmout.tv_usec = 0;
425 
426 	ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout);
427 	if (ret < 0 || FD_ISSET(intf->fd, &err_set) || !FD_ISSET(intf->fd, &read_set))
428 		return NULL;
429 
430 	/* the first read may return ECONNREFUSED because the rmcp ping
431 	 * packet--sent to UDP port 623--will be processed by both the
432 	 * BMC and the OS.
433 	 *
434 	 * The problem with this is that the ECONNREFUSED takes
435 	 * priority over any other received datagram; that means that
436 	 * the Connection Refused shows up _before_ the response packet,
437 	 * regardless of the order they were sent out.  (unless the
438 	 * response is read before the connection refused is returned)
439 	 */
440 	ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0);
441 
442 	if (ret < 0) {
443 		FD_ZERO(&read_set);
444 		FD_SET(intf->fd, &read_set);
445 
446 		FD_ZERO(&err_set);
447 		FD_SET(intf->fd, &err_set);
448 
449 		tmout.tv_sec = intf->session->timeout;
450 		tmout.tv_usec = 0;
451 
452 		ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout);
453 		if (ret < 0 || FD_ISSET(intf->fd, &err_set) || !FD_ISSET(intf->fd, &read_set))
454 			return NULL;
455 
456 		ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0);
457 		if (ret < 0)
458 			return NULL;
459 	}
460 
461 	if (ret == 0)
462 		return NULL;
463 
464 	rsp.data[ret] = '\0';
465 	rsp.data_len = ret;
466 
467 	if (verbose >= 5)
468 		printbuf(rsp.data, rsp.data_len, "<< received packet");
469 
470 	return &rsp;
471 }
472 
473 
474 
475 /*
476  * parse response RMCP "pong" packet
477  *
478  * return -1 if ping response not received
479  * returns 0 if IPMI is NOT supported
480  * returns 1 if IPMI is supported
481  *
482  * udp.source	= 0x026f	// RMCP_UDP_PORT
483  * udp.dest	= ?		// udp.source from rmcp-ping
484  * udp.len	= ?
485  * udp.check	= ?
486  * rmcp.ver	= 0x06		// RMCP Version 1.0
487  * rmcp.__res	= 0x00		// RESERVED
488  * rmcp.seq	= 0xff		// no RMCP ACK
489  * rmcp.class	= 0x06		// RMCP_CLASS_ASF
490  * asf.iana	= 0x000011be	// ASF_RMCP_IANA
491  * asf.type	= 0x40		// ASF_TYPE_PONG
492  * asf.tag	= ?		// asf.tag from rmcp-ping
493  * asf.__res	= 0x00		// RESERVED
494  * asf.len	= 0x10		// 16 bytes
495  * asf.data[3:0]= 0x000011be	// IANA# = RMCP_ASF_IANA if no OEM
496  * asf.data[7:4]= 0x00000000	// OEM-defined (not for IPMI)
497  * asf.data[8]	= 0x81		// supported entities
498  * 				// [7]=IPMI [6:4]=RES [3:0]=ASF_1.0
499  * asf.data[9]	= 0x00		// supported interactions (reserved)
500  * asf.data[f:a]= 0x000000000000
501  */
502 static int
ipmi_handle_pong(struct ipmi_intf * intf,struct ipmi_rs * rsp)503 ipmi_handle_pong(struct ipmi_intf * intf, struct ipmi_rs * rsp)
504 {
505 	struct rmcp_pong {
506 		struct rmcp_hdr rmcp;
507 		struct asf_hdr asf;
508 		uint32_t iana;
509 		uint32_t oem;
510 		uint8_t sup_entities;
511 		uint8_t sup_interact;
512 		uint8_t reserved[6];
513 	} * pong;
514 
515 	if (!rsp)
516 		return -1;
517 
518 	pong = (struct rmcp_pong *)rsp->data;
519 
520 	if (verbose)
521 		printf("Received IPMI/RMCP response packet: "
522 				"IPMI%s Supported\n",
523 				(pong->sup_entities & 0x80) ? "" : " NOT");
524 
525 	if (verbose > 1)
526 		printf("  ASF Version %s\n"
527 				"  RMCP Version %s\n"
528 				"  RMCP Sequence %d\n"
529 				"  IANA Enterprise %lu\n\n",
530 				(pong->sup_entities & 0x01) ? "1.0" : "unknown",
531 				(pong->rmcp.ver == 6) ? "1.0" : "unknown",
532 				pong->rmcp.seq,
533 				(unsigned long)ntohl(pong->iana));
534 
535 	return (pong->sup_entities & 0x80) ? 1 : 0;
536 }
537 
538 
539 /* build and send RMCP presence ping packet
540  *
541  * RMCP ping
542  *
543  * udp.source	= ?
544  * udp.dest	= 0x026f	// RMCP_UDP_PORT
545  * udp.len	= ?
546  * udp.check	= ?
547  * rmcp.ver	= 0x06		// RMCP Version 1.0
548  * rmcp.__res	= 0x00		// RESERVED
549  * rmcp.seq	= 0xff		// no RMCP ACK
550  * rmcp.class	= 0x06		// RMCP_CLASS_ASF
551  * asf.iana	= 0x000011be	// ASF_RMCP_IANA
552  * asf.type	= 0x80		// ASF_TYPE_PING
553  * asf.tag	= ?		// ASF sequence number
554  * asf.__res	= 0x00		// RESERVED
555  * asf.len	= 0x00
556  *
557  */
558 int
ipmiv2_lan_ping(struct ipmi_intf * intf)559 ipmiv2_lan_ping(struct ipmi_intf * intf)
560 {
561 	struct asf_hdr asf_ping = {
562 		.iana	= htonl(ASF_RMCP_IANA),
563 		.type	= ASF_TYPE_PING,
564 	};
565 	struct rmcp_hdr rmcp_ping = {
566 		.ver	= RMCP_VERSION_1,
567 		.class	= RMCP_CLASS_ASF,
568 		.seq	= 0xff,
569 	};
570 	uint8_t * data;
571 	int len = sizeof(rmcp_ping) + sizeof(asf_ping);
572 	int rv;
573 
574 	data = malloc(len);
575 	if (data == NULL) {
576 		lprintf(LOG_ERR, "ipmitool: malloc failure");
577 		return -1;
578 	}
579 	memset(data, 0, len);
580 	memcpy(data, &rmcp_ping, sizeof(rmcp_ping));
581 	memcpy(data+sizeof(rmcp_ping), &asf_ping, sizeof(asf_ping));
582 
583 	lprintf(LOG_DEBUG, "Sending IPMI/RMCP presence ping packet");
584 
585 	rv = ipmi_lan_send_packet(intf, data, len);
586 
587 	free(data);
588 	data = NULL;
589 
590 	if (rv < 0) {
591 		lprintf(LOG_ERR, "Unable to send IPMI presence ping packet");
592 		return -1;
593 	}
594 
595 	if (ipmi_lan_poll_recv(intf) == 0)
596 		return 0;
597 
598 	return 1;
599 }
600 
601 
602 /**
603  *
604  * ipmi_lan_poll_single
605  *
606  * Receive whatever comes back.  Ignore received packets that don't correspond
607  * to a request we've sent.
608  *
609  * Returns: the ipmi_rs packet describing the/a reponse we expect.
610  */
611 static struct ipmi_rs *
ipmi_lan_poll_single(struct ipmi_intf * intf)612 ipmi_lan_poll_single(struct ipmi_intf * intf)
613 {
614 	struct rmcp_hdr * rmcp_rsp;
615 	struct ipmi_rs * rsp;
616 	struct ipmi_session * session = intf->session;
617 	int offset, rv;
618 	uint16_t payload_size;
619 
620 	/* receive packet */
621 	rsp = ipmi_lan_recv_packet(intf);
622 
623 	/* check if no packet has come */
624 	if (rsp == NULL) {
625 		return NULL;
626 	}
627 
628 	/* parse response headers */
629 	rmcp_rsp = (struct rmcp_hdr *)rsp->data;
630 
631 	if (rmcp_rsp->class == RMCP_CLASS_ASF) {
632 		/* might be ping response packet */
633 		rv = ipmi_handle_pong(intf, rsp);
634 		return (rv <= 0) ? NULL : rsp;
635 	}
636 
637 	if (rmcp_rsp->class != RMCP_CLASS_IPMI) {
638 		lprintf(LOG_DEBUG, "Invalid RMCP class: %x", rmcp_rsp->class);
639 		/* read one more packet */
640 		return (struct ipmi_rs *)1;
641 	}
642 
643 	/*
644 	 * The authtype / payload type determines what we are receiving
645 	 */
646 	offset = 4;
647 
648 	/*--------------------------------------------------------------------
649 	 *
650 	 * The current packet could be one of several things:
651 	 *
652 	 * 1) An IPMI 1.5 packet (the response to our GET CHANNEL
653 	 *    AUTHENTICATION CAPABILITIES request)
654 	 * 2) An RMCP+ message with an IPMI reponse payload
655 	 * 3) AN RMCP+ open session response
656 	 * 4) An RAKP-2 message (response to an RAKP 1 message)
657 	 * 5) An RAKP-4 message (response to an RAKP 3 message)
658 	 * 6) A Serial Over LAN packet
659 	 * 7) An Invalid packet (one that doesn't match a request)
660 	 * -------------------------------------------------------------------
661 	 */
662 
663 	read_session_data(rsp, &offset, intf->session);
664 
665 	if (lanplus_has_valid_auth_code(rsp, intf->session) == 0) {
666 		lprintf(LOG_ERR, "ERROR: Received message with invalid authcode!");
667 		return NULL;
668 	}
669 
670 	if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE)    &&
671 			(rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
672 			(rsp->session.bEncrypted)) {
673 		lanplus_decrypt_payload(session->v2_data.crypt_alg,
674 				session->v2_data.k2,
675 				rsp->data + offset,
676 				rsp->session.msglen,
677 				rsp->data + offset,
678 				&payload_size);
679 	} else {
680 		payload_size = rsp->session.msglen;
681 	}
682 
683 	/*
684 	 * Handle IPMI responses (case #1 and #2) -- all IPMI reponses
685 	 */
686 	if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_IPMI) {
687 		struct ipmi_rq_entry * entry;
688 		int payload_start = offset;
689 		int extra_data_length;
690 		int loop = 1;
691 
692 		while (loop--) {
693 			/* fill-in response data */
694 			read_ipmi_response(rsp, &offset);
695 
696 			lprintf(LOG_DEBUG+1, "<< IPMI Response Session Header");
697 			lprintf(LOG_DEBUG+1, "<<   Authtype                : %s",
698 				val2str(rsp->session.authtype, ipmi_authtype_session_vals));
699 			lprintf(LOG_DEBUG+1, "<<   Payload type            : %s",
700 				val2str(rsp->session.payloadtype, plus_payload_types_vals));
701 			lprintf(LOG_DEBUG+1, "<<   Session ID              : 0x%08lx",
702 				(long)rsp->session.id);
703 			lprintf(LOG_DEBUG+1, "<<   Sequence                : 0x%08lx",
704 				(long)rsp->session.seq);
705 			lprintf(LOG_DEBUG+1, "<<   IPMI Msg/Payload Length : %d",
706 				rsp->session.msglen);
707 			lprintf(LOG_DEBUG+1, "<< IPMI Response Message Header");
708 			lprintf(LOG_DEBUG+1, "<<   Rq Addr    : %02x",
709 				rsp->payload.ipmi_response.rq_addr);
710 			lprintf(LOG_DEBUG+1, "<<   NetFn      : %02x",
711 				rsp->payload.ipmi_response.netfn);
712 			lprintf(LOG_DEBUG+1, "<<   Rq LUN     : %01x",
713 				rsp->payload.ipmi_response.rq_lun);
714 			lprintf(LOG_DEBUG+1, "<<   Rs Addr    : %02x",
715 				rsp->payload.ipmi_response.rs_addr);
716 			lprintf(LOG_DEBUG+1, "<<   Rq Seq     : %02x",
717 				rsp->payload.ipmi_response.rq_seq);
718 			lprintf(LOG_DEBUG+1, "<<   Rs Lun     : %01x",
719 				rsp->payload.ipmi_response.rs_lun);
720 			lprintf(LOG_DEBUG+1, "<<   Command    : %02x",
721 				rsp->payload.ipmi_response.cmd);
722 			lprintf(LOG_DEBUG+1, "<<   Compl Code : 0x%02x",
723 				rsp->ccode);
724 
725 			/* Are we expecting this packet? */
726 			entry = ipmi_req_lookup_entry(rsp->payload.ipmi_response.rq_seq,
727 								rsp->payload.ipmi_response.cmd);
728 
729 			if (entry == NULL) {
730 				lprintf(LOG_INFO, "IPMI Request Match NOT FOUND");
731 				/* read one more packet */
732 				return (struct ipmi_rs *)1;
733 			};
734 
735 			uint8_t target_cmd = entry->req.msg.target_cmd;
736 
737 			lprintf(LOG_DEBUG+2, "IPMI Request Match found");
738 
739 			if (entry->bridging_level) {
740 				/* Check completion code */
741 				if (rsp->ccode) {
742 					lprintf(LOG_DEBUG, "WARNING: Bridged "
743 							"cmd ccode = 0x%02x", rsp->ccode);
744 				} else {
745 					/* decrement bridging level */
746 					entry->bridging_level--;
747 					if (!entry->bridging_level) {
748 						entry->req.msg.cmd = entry->req.msg.target_cmd;
749 					}
750 
751 					/* check if bridged response is embedded */
752 					if (payload_size > 8) {
753 						printbuf(&rsp->data[offset], (rsp->data_len-offset-1),
754 								"bridge command response");
755 						/*
756 						 * decrement payload size
757 						 * (cks2 for outer Send Message)
758 						 */
759 						payload_size--;
760 
761 						/*
762 						 * need to make a loop for embedded bridged response
763 						 */
764 						loop++;
765 					} else {
766 						lprintf(LOG_DEBUG, "Bridged command answer,"
767 								" waiting for next answer... ");
768 						/* read one more packet */
769 						return (struct ipmi_rs *)1;
770 					}
771 				}
772 			}
773 
774 			/* Remove request entry */
775 			ipmi_req_remove_entry(rsp->payload.ipmi_response.rq_seq,
776 					rsp->payload.ipmi_response.cmd);
777 
778 			/*
779 			 * Good packet.  Shift response data to start of array.
780 			 * rsp->data becomes the variable length IPMI response data
781 			 * rsp->data_len becomes the length of that data
782 			 */
783 			extra_data_length = payload_size - (offset - payload_start) - 1;
784 			if (extra_data_length) {
785 				rsp->data_len = extra_data_length;
786 				memmove(rsp->data, rsp->data + offset, extra_data_length);
787 			} else {
788 				rsp->data_len = 0;
789 			}
790 		}
791 	/*
792 	 * Open Response
793 	 */
794 	} else if (rsp->session.payloadtype ==
795 			IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE) {
796 		if (session->v2_data.session_state !=
797 				LANPLUS_STATE_OPEN_SESSION_SENT) {
798 			lprintf(LOG_ERR, "Error: Received an Unexpected Open Session "
799 					"Response");
800 			/* read one more packet */
801 			return (struct ipmi_rs *)1;
802 		}
803 		read_open_session_response(rsp, offset);
804 	/*
805 	 * RAKP 2
806 	 */
807 	} else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_2) {
808 		if (session->v2_data.session_state != LANPLUS_STATE_RAKP_1_SENT) {
809 			lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 2 message");
810 			/* read one more packet */
811 			return (struct ipmi_rs *)1;
812 		}
813 		read_rakp2_message(rsp, offset, session->v2_data.auth_alg);
814 	/*
815 	 * RAKP 4
816 	 */
817 	} else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_4) {
818 		if (session->v2_data.session_state != LANPLUS_STATE_RAKP_3_SENT) {
819 			lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 4 message");
820 			/* read one more packet */
821 			return (struct ipmi_rs *)1;
822 		}
823 		read_rakp4_message(rsp, offset, session->v2_data.auth_alg);
824 	/*
825 	 * SOL
826 	 */
827 	} else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) {
828 		int payload_start = offset;
829 		int extra_data_length;
830 
831 		if (session->v2_data.session_state != LANPLUS_STATE_ACTIVE) {
832 			lprintf(LOG_ERR, "Error: Received an Unexpected SOL packet");
833 			/* read one more packet */
834 			return (struct ipmi_rs *)1;
835 		}
836 		read_sol_packet(rsp, &offset);
837 		extra_data_length = payload_size - (offset - payload_start);
838 		if (rsp && extra_data_length) {
839 			rsp->data_len = extra_data_length;
840 			memmove(rsp->data, rsp->data + offset, extra_data_length);
841 		} else {
842 			rsp->data_len = 0;
843 		}
844 	/*
845 	 * Unknown Payload type
846 	 */
847 	} else {
848 		lprintf(LOG_ERR, "Invalid RMCP+ payload type : 0x%x",
849 				rsp->session.payloadtype);
850 		/* read one more packet */
851 		return (struct ipmi_rs *)1;
852 	}
853 
854 	return rsp;
855 }
856 
857 
858 
859 /**
860  *
861  * ipmi_lan_poll_recv
862  *
863  * Receive whatever comes back.  Ignore received packets that don't correspond
864  * to a request we've sent.
865  *
866  * Returns: the ipmi_rs packet describing the/a reponse we expect.
867  */
868 static struct ipmi_rs *
ipmi_lan_poll_recv(struct ipmi_intf * intf)869 ipmi_lan_poll_recv(struct ipmi_intf * intf)
870 {
871 	struct ipmi_rs * rsp;
872 
873 	do {
874 		/* poll single packet */
875 		rsp = ipmi_lan_poll_single(intf);
876 	} while (rsp == (struct ipmi_rs *) 1);
877 
878 	return rsp;
879 }
880 
881 
882 
883 /*
884  * read_open_session_reponse
885  *
886  * Initialize the ipmi_rs from the IPMI 2.x open session response data.
887  *
888  * The offset should point to the first byte of the the Open Session Response
889  * payload when this function is called.
890  *
891  * param rsp    [in/out] reading from the data and writing to the open_session_response
892  *              section
893  * param offset [in] tells us where the Open Session Response payload starts
894  *
895  * returns 0 on success, 1 on error
896  */
897 void
read_open_session_response(struct ipmi_rs * rsp,int offset)898 read_open_session_response(struct ipmi_rs * rsp, int offset)
899 {
900 	memset(&rsp->payload.open_session_response, 0,
901 			 sizeof(rsp->payload.open_session_response));
902 
903 	 /*  Message tag */
904 	 rsp->payload.open_session_response.message_tag = rsp->data[offset];
905 
906 	 /* RAKP reponse code */
907 	 rsp->payload.open_session_response.rakp_return_code = rsp->data[offset + 1];
908 
909 	 /* Maximum privilege level */
910 	 rsp->payload.open_session_response.max_priv_level = rsp->data[offset + 2];
911 
912 	 /*** offset + 3 is reserved ***/
913 
914 	 /* Remote console session ID */
915 	 memcpy(&(rsp->payload.open_session_response.console_id),
916 			rsp->data + offset + 4,
917 			4);
918 	 #if WORDS_BIGENDIAN
919 	 rsp->payload.open_session_response.console_id =
920 		 BSWAP_32(rsp->payload.open_session_response.console_id);
921 	 #endif
922 
923 	/* only tag, status, privlvl, and console id are returned if error */
924 	 if (rsp->payload.open_session_response.rakp_return_code !=
925 		  IPMI_RAKP_STATUS_NO_ERRORS)
926 		 return;
927 
928 	 /* BMC session ID */
929 	 memcpy(&(rsp->payload.open_session_response.bmc_id),
930 			rsp->data + offset + 8,
931 			4);
932 	 #if WORDS_BIGENDIAN
933 	 rsp->payload.open_session_response.bmc_id =
934 		 BSWAP_32(rsp->payload.open_session_response.bmc_id);
935 	 #endif
936 
937 	 /* And of course, our negotiated algorithms */
938 	 rsp->payload.open_session_response.auth_alg      = rsp->data[offset + 16];
939 	 rsp->payload.open_session_response.integrity_alg = rsp->data[offset + 24];
940 	 rsp->payload.open_session_response.crypt_alg     = rsp->data[offset + 32];
941 }
942 
943 
944 
945 /*
946  * read_rakp2_message
947  *
948  * Initialize the ipmi_rs from the IPMI 2.x RAKP 2 message
949  *
950  * The offset should point the first byte of the the RAKP 2 payload when this
951  * function is called.
952  *
953  * param rsp [in/out] reading from the data variable and writing to the rakp 2
954  *       section
955  * param offset [in] tells us where hte rakp2 payload starts
956  * param auth_alg [in] describes the authentication algorithm was agreed upon in
957  *       the open session request/response phase.  We need to know that here so
958  *       that we know how many bytes (if any) to read fromt the packet.
959  *
960  * returns 0 on success, 1 on error
961  */
962 void
read_rakp2_message(struct ipmi_rs * rsp,int offset,uint8_t auth_alg)963 read_rakp2_message(
964 					struct ipmi_rs * rsp,
965 					int offset,
966 					uint8_t auth_alg)
967 {
968 	 int i;
969 
970 	 /*  Message tag */
971 	 rsp->payload.rakp2_message.message_tag = rsp->data[offset];
972 
973 	 /* RAKP reponse code */
974 	 rsp->payload.rakp2_message.rakp_return_code = rsp->data[offset + 1];
975 
976 	 /* Console session ID */
977 	 memcpy(&(rsp->payload.rakp2_message.console_id),
978 			rsp->data + offset + 4,
979 			4);
980 	 #if WORDS_BIGENDIAN
981 	 rsp->payload.rakp2_message.console_id =
982 		 BSWAP_32(rsp->payload.rakp2_message.console_id);
983 	 #endif
984 
985 	 /* BMC random number */
986 	 memcpy(&(rsp->payload.rakp2_message.bmc_rand),
987 			rsp->data + offset + 8,
988 			16);
989 	 #if WORDS_BIGENDIAN
990 	 lanplus_swap(rsp->payload.rakp2_message.bmc_rand, 16);
991 	 #endif
992 
993 	 /* BMC GUID */
994 	 memcpy(&(rsp->payload.rakp2_message.bmc_guid),
995 			rsp->data + offset + 24,
996 			16);
997 	 #if WORDS_BIGENDIAN
998 	 lanplus_swap(rsp->payload.rakp2_message.bmc_guid, 16);
999 	 #endif
1000 
1001 	 /* Key exchange authentication code */
1002 	 switch (auth_alg)
1003 	 {
1004 	 case  IPMI_AUTH_RAKP_NONE:
1005 		 /* Nothing to do here */
1006 		 break;
1007 
1008 	 case IPMI_AUTH_RAKP_HMAC_SHA1:
1009 		 /* We need to copy 20 bytes */
1010 		 for (i = 0; i < 20; ++i)
1011 			 rsp->payload.rakp2_message.key_exchange_auth_code[i] =
1012 				 rsp->data[offset + 40 + i];
1013 		 break;
1014 
1015 	 case IPMI_AUTH_RAKP_HMAC_MD5:
1016 		lprintf(LOG_ERR, "read_rakp2_message: no support for "
1017 				"IPMI_AUTH_RAKP_HMAC_MD5");
1018 		 assert(0);
1019 		 break;
1020 	 }
1021 }
1022 
1023 
1024 
1025 /*
1026  * read_rakp4_message
1027  *
1028  * Initialize the ipmi_rs from the IPMI 2.x RAKP 4 message
1029  *
1030  * The offset should point the first byte of the the RAKP 4 payload when this
1031  * function is called.
1032  *
1033  * param rsp [in/out] reading from the data variable and writing to the rakp
1034  *       4 section
1035  * param offset [in] tells us where hte rakp4 payload starts
1036  * param integrity_alg [in] describes the authentication algorithm was
1037  *       agreed upon in the open session request/response phase.  We need
1038  *       to know that here so that we know how many bytes (if any) to read
1039  *       from the packet.
1040  *
1041  * returns 0 on success, 1 on error
1042  */
1043 void
read_rakp4_message(struct ipmi_rs * rsp,int offset,uint8_t auth_alg)1044 read_rakp4_message(
1045 					struct ipmi_rs * rsp,
1046 					int offset,
1047 					uint8_t auth_alg)
1048 {
1049 	 int i;
1050 
1051 	 /*  Message tag */
1052 	 rsp->payload.rakp4_message.message_tag = rsp->data[offset];
1053 
1054 	 /* RAKP reponse code */
1055 	 rsp->payload.rakp4_message.rakp_return_code = rsp->data[offset + 1];
1056 
1057 	 /* Console session ID */
1058 	 memcpy(&(rsp->payload.rakp4_message.console_id),
1059 			rsp->data + offset + 4,
1060 			4);
1061 	 #if WORDS_BIGENDIAN
1062 	 rsp->payload.rakp4_message.console_id =
1063 		 BSWAP_32(rsp->payload.rakp4_message.console_id);
1064 	 #endif
1065 
1066 
1067 	 /* Integrity check value */
1068 	 switch (auth_alg)
1069 	 {
1070 	 case  IPMI_AUTH_RAKP_NONE:
1071 		 /* Nothing to do here */
1072 		 break;
1073 
1074 	 case IPMI_AUTH_RAKP_HMAC_SHA1:
1075 		 /* We need to copy 12 bytes */
1076 		 for (i = 0; i < 12; ++i)
1077 			 rsp->payload.rakp4_message.integrity_check_value[i] =
1078 				 rsp->data[offset + 8 + i];
1079 		 break;
1080 
1081 	 case IPMI_AUTH_RAKP_HMAC_MD5:
1082 		 lprintf(LOG_ERR, "read_rakp4_message: no support "
1083 			 "for authentication algorithm 0x%x", auth_alg);
1084 		 assert(0);
1085 		 break;
1086 	 }
1087 }
1088 
1089 
1090 
1091 
1092 /*
1093  * read_session_data
1094  *
1095  * Initialize the ipmi_rsp from the session data in the packet
1096  *
1097  * The offset should point the first byte of the the IPMI session when this
1098  * function is called.
1099  *
1100  * param rsp     [in/out] we read from the data buffer and populate the session
1101  *               specific fields.
1102  * param offset  [in/out] should point to the beginning of the session when
1103  *               this function is called.  The offset will be adjusted to
1104  *               point to the end of the session when this function exits.
1105  * param session holds our session state
1106  */
1107 void
read_session_data(struct ipmi_rs * rsp,int * offset,struct ipmi_session * s)1108 read_session_data(
1109 				  struct ipmi_rs * rsp,
1110 				  int * offset,
1111 				  struct ipmi_session * s)
1112 {
1113 	/* We expect to read different stuff depending on the authtype */
1114 	rsp->session.authtype = rsp->data[*offset];
1115 
1116 	if (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS)
1117 		read_session_data_v2x(rsp, offset, s);
1118 	else
1119 		read_session_data_v15(rsp, offset, s);
1120 }
1121 
1122 
1123 
1124 /*
1125  * read_session_data_v2x
1126  *
1127  * Initialize the ipmi_rsp from the v2.x session header of the packet.
1128  *
1129  * The offset should point to the first byte of the the IPMI session when this
1130  * function is called.  When this function exits, offset will point to the
1131  * start of payload.
1132  *
1133  * Should decrypt and perform integrity checking here?
1134  *
1135  * param rsp    [in/out] we read from the data buffer and populate the session
1136  *              specific fields.
1137  * param offset [in/out] should point to the beginning of the session when this
1138  *              function is called.  The offset will be adjusted to point to
1139  *              the end of the session when this function exits.
1140  *  param s      holds our session state
1141  */
1142 void
read_session_data_v2x(struct ipmi_rs * rsp,int * offset,struct ipmi_session * s)1143 read_session_data_v2x(
1144 					  struct ipmi_rs      * rsp,
1145 					  int                 * offset,
1146 					  struct ipmi_session * s)
1147 {
1148 	rsp->session.authtype = rsp->data[(*offset)++];
1149 
1150 	rsp->session.bEncrypted     = (rsp->data[*offset] & 0x80 ? 1 : 0);
1151 	rsp->session.bAuthenticated = (rsp->data[*offset] & 0x40 ? 1 : 0);
1152 
1153 
1154 	/* Payload type */
1155 	rsp->session.payloadtype = rsp->data[(*offset)++] & 0x3F;
1156 
1157 	/* Session ID */
1158 	memcpy(&rsp->session.id, rsp->data + *offset, 4);
1159 	*offset += 4;
1160 	#if WORDS_BIGENDIAN
1161 	rsp->session.id = BSWAP_32(rsp->session.id);
1162 	#endif
1163 
1164 
1165 	/*
1166 	 * Verify that the session ID is what we think it should be
1167 	 */
1168 	if ((s->v2_data.session_state == LANPLUS_STATE_ACTIVE) &&
1169 		(rsp->session.id != s->v2_data.console_id))
1170 	{
1171 		lprintf(LOG_ERR, "packet session id 0x%x does not "
1172 			"match active session 0x%0x",
1173 			rsp->session.id, s->v2_data.console_id);
1174 		assert(0);
1175 	}
1176 
1177 
1178 	/* Ignored, so far */
1179 	memcpy(&rsp->session.seq, rsp->data + *offset, 4);
1180 	*offset += 4;
1181 	#if WORDS_BIGENDIAN
1182 	rsp->session.seq = BSWAP_32(rsp->session.seq);
1183 	#endif
1184 
1185 	memcpy(&rsp->session.msglen, rsp->data + *offset, 2);
1186 	*offset += 2;
1187 	#if WORDS_BIGENDIAN
1188 	rsp->session.msglen = BSWAP_16(rsp->session.msglen);
1189 	#endif
1190 }
1191 
1192 
1193 
1194 /*
1195  * read_session_data_v15
1196  *
1197  * Initialize the ipmi_rsp from the session header of the packet.
1198  *
1199  * The offset should point the first byte of the the IPMI session when this
1200  * function is called.  When this function exits, the offset will point to
1201  * the start of the IPMI message.
1202  *
1203  * param rsp    [in/out] we read from the data buffer and populate the session
1204  *              specific fields.
1205  * param offset [in/out] should point to the beginning of the session when this
1206  *              function is called.  The offset will be adjusted to point to the
1207  *              end of the session when this function exits.
1208  * param s      holds our session state
1209  */
read_session_data_v15(struct ipmi_rs * rsp,int * offset,struct ipmi_session * s)1210 void read_session_data_v15(
1211 							struct ipmi_rs * rsp,
1212 							int * offset,
1213 							struct ipmi_session * s)
1214 {
1215 	/* All v15 messages are IPMI messages */
1216 	rsp->session.payloadtype = IPMI_PAYLOAD_TYPE_IPMI;
1217 
1218 	rsp->session.authtype = rsp->data[(*offset)++];
1219 
1220 	/* All v15 messages that we will receive are unencrypted/unauthenticated */
1221 	rsp->session.bEncrypted     = 0;
1222 	rsp->session.bAuthenticated = 0;
1223 
1224 	/* skip the session id and sequence number fields */
1225 	*offset += 8;
1226 
1227 	/* This is the size of the whole payload */
1228 	rsp->session.msglen = rsp->data[(*offset)++];
1229 }
1230 
1231 
1232 
1233 /*
1234  * read_ipmi_response
1235  *
1236  * Initialize the ipmi_rs from with the IPMI response specific data
1237  *
1238  * The offset should point the first byte of the the IPMI payload when this
1239  * function is called.
1240  *
1241  * param rsp    [in/out] we read from the data buffer and populate the IPMI
1242  *              specific fields.
1243  * param offset [in/out] should point to the beginning of the IPMI payload when
1244  *              this function is called.
1245  */
read_ipmi_response(struct ipmi_rs * rsp,int * offset)1246 void read_ipmi_response(struct ipmi_rs * rsp, int * offset)
1247 {
1248 	/*
1249 	 * The data here should be decrypted by now.
1250 	 */
1251 	rsp->payload.ipmi_response.rq_addr = rsp->data[(*offset)++];
1252 	rsp->payload.ipmi_response.netfn   = rsp->data[*offset] >> 2;
1253 	rsp->payload.ipmi_response.rq_lun  = rsp->data[(*offset)++] & 0x3;
1254 	(*offset)++;		/* checksum */
1255 	rsp->payload.ipmi_response.rs_addr = rsp->data[(*offset)++];
1256 	rsp->payload.ipmi_response.rq_seq  = rsp->data[*offset] >> 2;
1257 	rsp->payload.ipmi_response.rs_lun  = rsp->data[(*offset)++] & 0x3;
1258 	rsp->payload.ipmi_response.cmd     = rsp->data[(*offset)++];
1259 	rsp->ccode                         = rsp->data[(*offset)++];
1260 
1261 }
1262 
1263 
1264 
1265 /*
1266  * read_sol_packet
1267  *
1268  * Initialize the ipmi_rs with the SOL response data
1269  *
1270  * The offset should point the first byte of the the SOL payload when this
1271  * function is called.
1272  *
1273  * param rsp    [in/out] we read from the data buffer and populate the
1274  *              SOL specific fields.
1275  * param offset [in/out] should point to the beginning of the SOL payload
1276  *              when this function is called.
1277  */
read_sol_packet(struct ipmi_rs * rsp,int * offset)1278 void read_sol_packet(struct ipmi_rs * rsp, int * offset)
1279 {
1280 
1281 	/*
1282 	 * The data here should be decrypted by now.
1283 	 */
1284 	rsp->payload.sol_packet.packet_sequence_number =
1285 		rsp->data[(*offset)++] & 0x0F;
1286 
1287 	rsp->payload.sol_packet.acked_packet_number =
1288 		rsp->data[(*offset)++] & 0x0F;
1289 
1290 	rsp->payload.sol_packet.accepted_character_count =
1291 		rsp->data[(*offset)++];
1292 
1293 	rsp->payload.sol_packet.is_nack =
1294 		rsp->data[*offset] & 0x40;
1295 
1296 	rsp->payload.sol_packet.transfer_unavailable =
1297 		rsp->data[*offset] & 0x20;
1298 
1299 	rsp->payload.sol_packet.sol_inactive =
1300 		rsp->data[*offset] & 0x10;
1301 
1302 	rsp->payload.sol_packet.transmit_overrun =
1303 		rsp->data[*offset] & 0x08;
1304 
1305 	rsp->payload.sol_packet.break_detected =
1306 		rsp->data[(*offset)++] & 0x04;
1307 
1308 	lprintf(LOG_DEBUG, "<<<<<<<<<< RECV FROM BMC <<<<<<<<<<<");
1309 	lprintf(LOG_DEBUG, "< SOL sequence number     : 0x%02x",
1310 		rsp->payload.sol_packet.packet_sequence_number);
1311 	lprintf(LOG_DEBUG, "< SOL acked packet        : 0x%02x",
1312 		rsp->payload.sol_packet.acked_packet_number);
1313 	lprintf(LOG_DEBUG, "< SOL accepted char count : 0x%02x",
1314 		rsp->payload.sol_packet.accepted_character_count);
1315 	lprintf(LOG_DEBUG, "< SOL is nack             : %s",
1316 		rsp->payload.sol_packet.is_nack? "true" : "false");
1317 	lprintf(LOG_DEBUG, "< SOL xfer unavailable    : %s",
1318 		rsp->payload.sol_packet.transfer_unavailable? "true" : "false");
1319 	lprintf(LOG_DEBUG, "< SOL inactive            : %s",
1320 		rsp->payload.sol_packet.sol_inactive? "true" : "false");
1321 	lprintf(LOG_DEBUG, "< SOL transmit overrun    : %s",
1322 		rsp->payload.sol_packet.transmit_overrun? "true" : "false");
1323 	lprintf(LOG_DEBUG, "< SOL break detected      : %s",
1324 		rsp->payload.sol_packet.break_detected? "true" : "false");
1325 	lprintf(LOG_DEBUG, "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
1326 
1327 	if (verbose >= 5)
1328 		printbuf(rsp->data + *offset - 4, 4, "SOL MSG FROM BMC");
1329 }
1330 
1331 
1332 
1333 /*
1334  * getIpmiPayloadWireRep
1335  *
1336  * param out [out] will contain our wire representation
1337  * param req [in] is the IPMI request to be written
1338  * param crypt_alg [in] specifies the encryption to use
1339  * param rq_seq [in] is the IPMI command sequence number.
1340  */
getIpmiPayloadWireRep(struct ipmi_intf * intf,struct ipmi_v2_payload * payload,uint8_t * msg,struct ipmi_rq * req,uint8_t rq_seq,uint8_t curr_seq)1341 void getIpmiPayloadWireRep(
1342 							struct ipmi_intf       * intf,  /* in out */
1343 							struct ipmi_v2_payload * payload,  /* in  */
1344 							uint8_t  * msg,
1345 							struct ipmi_rq * req,
1346 							uint8_t    rq_seq,
1347 							uint8_t curr_seq)
1348 {
1349 	int cs, tmp, len;
1350 	int cs2 = 0;
1351 	int cs3 = 0;
1352 	uint8_t ourAddress = intf->my_addr;
1353 	uint8_t bridgedRequest = 0;
1354 
1355 	if (ourAddress == 0)
1356 		ourAddress = IPMI_BMC_SLAVE_ADDR;
1357 
1358 	len = 0;
1359 
1360 	/* IPMI Message Header -- Figure 13-4 of the IPMI v2.0 spec */
1361 	if ((intf->target_addr == ourAddress) || (!bridgePossible)) {
1362 		cs = len;
1363 	} else {
1364 		bridgedRequest = 1;
1365 
1366 		if(intf->transit_addr != ourAddress && intf->transit_addr != 0)
1367 		{
1368 			bridgedRequest++;
1369 		}
1370 		/* bridged request: encapsulate w/in Send Message */
1371 		cs = len;
1372 		msg[len++] = IPMI_BMC_SLAVE_ADDR;
1373 		msg[len++] = IPMI_NETFN_APP << 2;
1374 		tmp = len - cs;
1375 		msg[len++] = ipmi_csum(msg+cs, tmp);
1376 		cs2 = len;
1377 		msg[len++] = IPMI_REMOTE_SWID;
1378 		msg[len++] = curr_seq << 2;
1379 
1380 
1381 		msg[len++] = 0x34;			/* Send Message rqst */
1382 		if(bridgedRequest == 2)
1383 			msg[len++] = (0x40|intf->transit_channel); /* Track request*/
1384 		else
1385 			msg[len++] = (0x40|intf->target_channel);    /* Track request*/
1386 
1387 		payload->payload_length += 7;
1388 		cs = len;
1389 
1390 		if(bridgedRequest == 2)
1391 		{
1392 			/* bridged request: encapsulate w/in Send Message */
1393 			cs = len;
1394 			msg[len++] = intf->transit_addr;
1395 			msg[len++] = IPMI_NETFN_APP << 2;
1396 			tmp = len - cs;
1397 			msg[len++] = ipmi_csum(msg+cs, tmp);
1398 			cs3 = len;
1399 			msg[len++] = IPMI_REMOTE_SWID;
1400 			msg[len++] = curr_seq << 2;
1401 			msg[len++] = 0x34;			/* Send Message rqst */
1402 	#if 0  /* From lan.c example */
1403 			entry->req.msg.target_cmd = entry->req.msg.cmd;	/* Save target command */
1404 			entry->req.msg.cmd = 0x34;		/* (fixup request entry) */
1405 	#endif
1406 			msg[len++] = (0x40|intf->target_channel); /* Track request*/
1407 
1408 			payload->payload_length += 7;
1409 
1410 			cs = len;
1411 		}
1412 	}
1413 
1414         lprintf(LOG_DEBUG,"%s RqAddr %#x transit %#x:%#x target %#x:%#x "
1415 		"bridgePossible %d",
1416 		bridgedRequest ? "Bridging" : "Local",
1417 		intf->my_addr, intf->transit_addr, intf->transit_channel,
1418 		intf->target_addr, intf->target_channel,
1419 		bridgePossible);
1420 
1421 	/* rsAddr */
1422 	if (bridgedRequest)
1423 		msg[len++] = intf->target_addr;
1424 	else
1425 		msg[len++] = IPMI_BMC_SLAVE_ADDR;
1426 
1427 	/* net Fn */
1428 	msg[len++] = req->msg.netfn << 2 | (req->msg.lun & 3);
1429 	tmp = len - cs;
1430 
1431 	/* checkSum */
1432 	msg[len++] = ipmi_csum(msg+cs, tmp);
1433 	cs = len;
1434 
1435 	/* rqAddr */
1436 	if (bridgedRequest < 2)
1437 		msg[len++] = IPMI_REMOTE_SWID;
1438 	else  /* Bridged message */
1439 		msg[len++] = intf->my_addr;
1440 
1441 	/* rqSeq / rqLUN */
1442 	msg[len++] = rq_seq << 2;
1443 
1444 	/* cmd */
1445 	msg[len++] = req->msg.cmd;
1446 
1447 	/* message data */
1448 	if (req->msg.data_len) {
1449 		memcpy(msg + len, req->msg.data, req->msg.data_len);
1450 		len += req->msg.data_len;
1451 	}
1452 
1453 	/* second checksum */
1454 	tmp = len - cs;
1455 	msg[len++] = ipmi_csum(msg+cs, tmp);
1456 
1457 	/* Dual bridged request: 2nd checksum */
1458 	if (bridgedRequest == 2) {
1459 		tmp = len - cs3;
1460 		msg[len++] = ipmi_csum(msg+cs3, tmp);
1461 		payload->payload_length += 1;
1462 	}
1463 
1464 	/* bridged request: 2nd checksum */
1465 	if (bridgedRequest) {
1466 		tmp = len - cs2;
1467 		msg[len++] = ipmi_csum(msg+cs2, tmp);
1468 		payload->payload_length += 1;
1469 	}
1470 }
1471 
1472 
1473 
1474 /*
1475  * getSolPayloadWireRep
1476  *
1477  * param msg [out] will contain our wire representation
1478  * param payload [in] holds the v2 payload with our SOL data
1479  */
getSolPayloadWireRep(struct ipmi_intf * intf,uint8_t * msg,struct ipmi_v2_payload * payload)1480 void getSolPayloadWireRep(
1481 						  struct ipmi_intf       * intf,  /* in out */
1482 						  uint8_t          * msg,     /* output */
1483 						  struct ipmi_v2_payload * payload) /* input */
1484 {
1485 	int i = 0;
1486 
1487 	lprintf(LOG_DEBUG, ">>>>>>>>>> SENDING TO BMC >>>>>>>>>>");
1488 	lprintf(LOG_DEBUG, "> SOL sequence number     : 0x%02x",
1489 		payload->payload.sol_packet.packet_sequence_number);
1490 	lprintf(LOG_DEBUG, "> SOL acked packet        : 0x%02x",
1491 		payload->payload.sol_packet.acked_packet_number);
1492 	lprintf(LOG_DEBUG, "> SOL accepted char count : 0x%02x",
1493 		payload->payload.sol_packet.accepted_character_count);
1494 	lprintf(LOG_DEBUG, "> SOL is nack             : %s",
1495 		payload->payload.sol_packet.is_nack ? "true" : "false");
1496 	lprintf(LOG_DEBUG, "> SOL assert ring wor     : %s",
1497 		payload->payload.sol_packet.assert_ring_wor ? "true" : "false");
1498 	lprintf(LOG_DEBUG, "> SOL generate break      : %s",
1499 		payload->payload.sol_packet.generate_break ? "true" : "false");
1500 	lprintf(LOG_DEBUG, "> SOL deassert cts        : %s",
1501 		payload->payload.sol_packet.deassert_cts ? "true" : "false");
1502 	lprintf(LOG_DEBUG, "> SOL deassert dcd dsr    : %s",
1503 		payload->payload.sol_packet.deassert_dcd_dsr ? "true" : "false");
1504 	lprintf(LOG_DEBUG, "> SOL flush inbound       : %s",
1505 		payload->payload.sol_packet.flush_inbound ? "true" : "false");
1506 	lprintf(LOG_DEBUG, "> SOL flush outbound      : %s",
1507 		payload->payload.sol_packet.flush_outbound ? "true" : "false");
1508 
1509 	msg[i++] = payload->payload.sol_packet.packet_sequence_number;
1510 	msg[i++] = payload->payload.sol_packet.acked_packet_number;
1511 	msg[i++] = payload->payload.sol_packet.accepted_character_count;
1512 
1513 	msg[i]    = payload->payload.sol_packet.is_nack           ? 0x40 : 0;
1514 	msg[i]   |= payload->payload.sol_packet.assert_ring_wor   ? 0x20 : 0;
1515 	msg[i]   |= payload->payload.sol_packet.generate_break    ? 0x10 : 0;
1516 	msg[i]   |= payload->payload.sol_packet.deassert_cts      ? 0x08 : 0;
1517 	msg[i]   |= payload->payload.sol_packet.deassert_dcd_dsr  ? 0x04 : 0;
1518 	msg[i]   |= payload->payload.sol_packet.flush_inbound     ? 0x02 : 0;
1519 	msg[i++] |= payload->payload.sol_packet.flush_outbound    ? 0x01 : 0;
1520 
1521 	/* We may have data to add */
1522 	memcpy(msg + i,
1523 			payload->payload.sol_packet.data,
1524 			payload->payload.sol_packet.character_count);
1525 
1526 	lprintf(LOG_DEBUG, "> SOL character count     : %d",
1527 		payload->payload.sol_packet.character_count);
1528 	lprintf(LOG_DEBUG, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
1529 
1530 	if (verbose >= 5 && payload->payload.sol_packet.character_count)
1531 		printbuf(payload->payload.sol_packet.data, payload->payload.sol_packet.character_count, "SOL SEND DATA");
1532 
1533 	/*
1534 	 * At this point, the payload length becomes the whole payload
1535 	 * length, including the 4 bytes at the beginning of the SOL
1536 	 * packet
1537 	 */
1538 	payload->payload_length = payload->payload.sol_packet.character_count + 4;
1539 }
1540 
1541 
1542 
1543 /*
1544  * ipmi_lanplus_build_v2x_msg
1545  *
1546  * Encapsulates the payload data to create the IPMI v2.0 / RMCP+ packet.
1547  *
1548  *
1549  * IPMI v2.0 LAN Request Message Format
1550  * +----------------------+
1551  * |  rmcp.ver            | 4 bytes
1552  * |  rmcp.__reserved     |
1553  * |  rmcp.seq            |
1554  * |  rmcp.class          |
1555  * +----------------------+
1556  * |  session.authtype    | 10 bytes
1557  * |  session.payloadtype |
1558  * |  session.id          |
1559  * |  session.seq         |
1560  * +----------------------+
1561  * |  message length      | 2 bytes
1562  * +----------------------+
1563  * | Confidentiality Hdr  | var (possibly absent)
1564  * +----------------------+
1565  * |  Paylod              | var Payload
1566  * +----------------------+
1567  * | Confidentiality Trlr | var (possibly absent)
1568  * +----------------------+
1569  * | Integrity pad        | var (possibly absent)
1570  * +----------------------+
1571  * | Pad length           | 1 byte (WTF?)
1572  * +----------------------+
1573  * | Next Header          | 1 byte (WTF?)
1574  * +----------------------+
1575  * | Authcode             | var (possibly absent)
1576  * +----------------------+
1577  */
1578 void
ipmi_lanplus_build_v2x_msg(struct ipmi_intf * intf,struct ipmi_v2_payload * payload,int * msg_len,uint8_t ** msg_data,uint8_t curr_seq)1579 ipmi_lanplus_build_v2x_msg(
1580 							struct ipmi_intf       * intf,     /* in  */
1581 							struct ipmi_v2_payload * payload,  /* in  */
1582 							int                    * msg_len,  /* out */
1583 							uint8_t         ** msg_data, /* out */
1584 							uint8_t curr_seq)
1585 {
1586 	uint32_t session_trailer_length = 0;
1587 	struct ipmi_session * session = intf->session;
1588 	struct rmcp_hdr rmcp = {
1589 		.ver		= RMCP_VERSION_1,
1590 		.class		= RMCP_CLASS_IPMI,
1591 		.seq		= 0xff,
1592 	};
1593 
1594 	/* msg will hold the entire message to be sent */
1595 	uint8_t * msg;
1596 	int len = 0;
1597 
1598 
1599 	len =
1600 		sizeof(rmcp)                +  // RMCP Header (4)
1601 		10                          +  // IPMI Session Header
1602 		2                           +  // Message length
1603 		payload->payload_length     +  // The actual payload
1604 		IPMI_MAX_INTEGRITY_PAD_SIZE +  // Integrity Pad
1605 		1                           +  // Pad Length
1606 		1                           +  // Next Header
1607 		IPMI_MAX_AUTH_CODE_SIZE;       // Authcode
1608 
1609 
1610 	msg = malloc(len);
1611 	if (msg == NULL) {
1612 		lprintf(LOG_ERR, "ipmitool: malloc failure");
1613 		return;
1614 	}
1615 	memset(msg, 0, len);
1616 
1617 	/*
1618 	 *------------------------------------------
1619 	 * RMCP HEADER
1620 	 *------------------------------------------
1621 	 */
1622 	memcpy(msg, &rmcp, sizeof(rmcp));
1623 	len = sizeof(rmcp);
1624 
1625 
1626 	/*
1627 	 *------------------------------------------
1628 	 * IPMI SESSION HEADER
1629 	 *------------------------------------------
1630 	 */
1631 	/* ipmi session Auth Type / Format is always 0x06 for IPMI v2 */
1632 	msg[IPMI_LANPLUS_OFFSET_AUTHTYPE] = 0x06;
1633 
1634 	/* Payload Type -- also specifies whether were authenticated/encyrpted */
1635 	msg[IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE] = payload->payload_type;
1636 
1637 	if (session->v2_data.session_state == LANPLUS_STATE_ACTIVE)
1638 	{
1639 		msg[IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE] |=
1640 			((session->v2_data.crypt_alg != IPMI_CRYPT_NONE	)? 0x80 : 0x00);
1641 		msg[IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE] |=
1642 			((session->v2_data.integrity_alg  != IPMI_INTEGRITY_NONE)? 0x40 : 0x00);
1643 	}
1644 
1645 	if (session->v2_data.session_state == LANPLUS_STATE_ACTIVE)
1646 	{
1647 		/* Session ID  -- making it LSB */
1648 		msg[IPMI_LANPLUS_OFFSET_SESSION_ID    ] = session->v2_data.bmc_id         & 0xff;
1649 		msg[IPMI_LANPLUS_OFFSET_SESSION_ID + 1] = (session->v2_data.bmc_id >> 8)  & 0xff;
1650 		msg[IPMI_LANPLUS_OFFSET_SESSION_ID + 2] = (session->v2_data.bmc_id >> 16) & 0xff;
1651 		msg[IPMI_LANPLUS_OFFSET_SESSION_ID + 3] = (session->v2_data.bmc_id >> 24) & 0xff;
1652 
1653 		/* Sequence Number -- making it LSB */
1654 		msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM    ] = session->out_seq         & 0xff;
1655 		msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM + 1] = (session->out_seq >> 8)  & 0xff;
1656 		msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM + 2] = (session->out_seq >> 16) & 0xff;
1657 		msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM + 3] = (session->out_seq >> 24) & 0xff;
1658 	}
1659 
1660 	/*
1661 	 * Payload Length is set below (we don't know how big the payload is until after
1662 	 * encryption).
1663 	 */
1664 
1665 	/*
1666 	 * Payload
1667 	 *
1668 	 * At this point we are ready to slam the payload in.
1669 	 * This includes:
1670 	 * 1) The confidentiality header
1671 	 * 2) The payload proper (possibly encrypted)
1672 	 * 3) The confidentiality trailer
1673 	 *
1674 	 */
1675 	switch (payload->payload_type)
1676 	{
1677 	case IPMI_PAYLOAD_TYPE_IPMI:
1678 		getIpmiPayloadWireRep(intf,
1679 							  payload,  /* in  */
1680 							  msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
1681 							  payload->payload.ipmi_request.request,
1682 							  payload->payload.ipmi_request.rq_seq,
1683 							  curr_seq);
1684 		break;
1685 
1686 	case IPMI_PAYLOAD_TYPE_SOL:
1687 		getSolPayloadWireRep(intf,
1688 							 msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
1689 							 payload);
1690 
1691 		if (verbose >= 5)
1692 			printbuf(msg + IPMI_LANPLUS_OFFSET_PAYLOAD, 4, "SOL MSG TO BMC");
1693 
1694 		len += payload->payload_length;
1695 
1696 		break;
1697 
1698 	case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST:
1699 		/* never encrypted, so our job is easy */
1700 		memcpy(msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
1701 				payload->payload.open_session_request.request,
1702 				payload->payload_length);
1703 		len += payload->payload_length;
1704 		break;
1705 
1706 	case IPMI_PAYLOAD_TYPE_RAKP_1:
1707 		/* never encrypted, so our job is easy */
1708 		memcpy(msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
1709 				payload->payload.rakp_1_message.message,
1710 				payload->payload_length);
1711 		len += payload->payload_length;
1712 		break;
1713 
1714 	case IPMI_PAYLOAD_TYPE_RAKP_3:
1715 		/* never encrypted, so our job is easy */
1716 		memcpy(msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
1717 				payload->payload.rakp_3_message.message,
1718 				payload->payload_length);
1719 		len += payload->payload_length;
1720 		break;
1721 
1722 	default:
1723 		lprintf(LOG_ERR, "unsupported payload type 0x%x",
1724 			payload->payload_type);
1725 		free(msg);
1726 		msg = NULL;
1727 		assert(0);
1728 		break;
1729 	}
1730 
1731 
1732 	/*
1733 	 *------------------------------------------
1734 	 * ENCRYPT THE PAYLOAD IF NECESSARY
1735 	 *------------------------------------------
1736 	 */
1737 	if (session->v2_data.session_state == LANPLUS_STATE_ACTIVE)
1738 	{
1739 		/* Payload len is adjusted as necessary by lanplus_encrypt_payload */
1740 		lanplus_encrypt_payload(session->v2_data.crypt_alg,        /* input  */
1741 								session->v2_data.k2,               /* input  */
1742 								msg + IPMI_LANPLUS_OFFSET_PAYLOAD, /* input  */
1743 								payload->payload_length,           /* input  */
1744 								msg + IPMI_LANPLUS_OFFSET_PAYLOAD, /* output */
1745 								&(payload->payload_length));       /* output */
1746 
1747 	}
1748 
1749 	/* Now we know the payload length */
1750 	msg[IPMI_LANPLUS_OFFSET_PAYLOAD_SIZE    ] =
1751 		payload->payload_length        & 0xff;
1752 	msg[IPMI_LANPLUS_OFFSET_PAYLOAD_SIZE + 1] =
1753 		(payload->payload_length >> 8) & 0xff;
1754 
1755 
1756 	/*
1757 	 *------------------------------------------
1758 	 * SESSION TRAILER
1759 	 *------------------------------------------
1760 	 */
1761 	if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) &&
1762 		(session->v2_data.integrity_alg != IPMI_INTEGRITY_NONE))
1763 	{
1764 		uint32_t i, hmac_length, integrity_pad_size = 0, hmac_input_size;
1765 		uint8_t * hmac_output;
1766 		uint32_t start_of_session_trailer =
1767 			IPMI_LANPLUS_OFFSET_PAYLOAD +
1768 			payload->payload_length;
1769 
1770 
1771 		/*
1772 		 * Determine the required integrity pad length.  We have to make the
1773 		 * data range covered by the authcode a multiple of 4.
1774 		 */
1775 		uint32_t length_before_authcode;
1776 
1777 		if (ipmi_oem_active(intf, "icts")) {
1778 			length_before_authcode =
1779 				12                          + /* the stuff before the payload */
1780 				payload->payload_length;
1781 		} else {
1782 			length_before_authcode =
1783 				12                          + /* the stuff before the payload */
1784 				payload->payload_length     +
1785 				1                           + /* pad length field  */
1786 				1;                            /* next header field */
1787 		}
1788 
1789 		if (length_before_authcode % 4)
1790 			integrity_pad_size = 4 - (length_before_authcode % 4);
1791 
1792 		for (i = 0; i < integrity_pad_size; ++i)
1793 			msg[start_of_session_trailer + i] = 0xFF;
1794 
1795 		/* Pad length */
1796 		msg[start_of_session_trailer + integrity_pad_size] = integrity_pad_size;
1797 
1798 		/* Next Header */
1799 		msg[start_of_session_trailer + integrity_pad_size + 1] =
1800 			0x07; /* Hardcoded per the spec, table 13-8 */
1801 
1802 		hmac_input_size =
1803 			12                      +
1804 			payload->payload_length +
1805 			integrity_pad_size      +
1806 			2;
1807 
1808 		hmac_output =
1809 			msg                         +
1810 			IPMI_LANPLUS_OFFSET_PAYLOAD +
1811 			payload->payload_length     +
1812 			integrity_pad_size          +
1813 			2;
1814 
1815 		if (verbose > 2)
1816 			printbuf(msg + IPMI_LANPLUS_OFFSET_AUTHTYPE, hmac_input_size, "authcode input");
1817 
1818 
1819 		/* Auth Code */
1820 		lanplus_HMAC(session->v2_data.integrity_alg,
1821 					 session->v2_data.k1,                /* key        */
1822 					 20,                                 /* key length */
1823 					 msg + IPMI_LANPLUS_OFFSET_AUTHTYPE, /* hmac input */
1824 					 hmac_input_size,
1825 					 hmac_output,
1826 					 &hmac_length);
1827 
1828 		assert(hmac_length == 20);
1829 
1830 		if (verbose > 2)
1831 			printbuf(hmac_output, 12, "authcode output");
1832 
1833 		/* Set session_trailer_length appropriately */
1834 		session_trailer_length =
1835 			integrity_pad_size +
1836 			2                  + /* pad length + next header */
1837 			12;                  /* Size of the authcode (we only use the first 12 bytes) */
1838 	}
1839 
1840 
1841 	++(session->out_seq);
1842 	if (!session->out_seq)
1843 		++(session->out_seq);
1844 
1845 	*msg_len =
1846 		IPMI_LANPLUS_OFFSET_PAYLOAD +
1847 		payload->payload_length     +
1848 		session_trailer_length;
1849 	*msg_data = msg;
1850 }
1851 
1852 
1853 
1854 /*
1855  * ipmi_lanplus_build_v2x_ipmi_cmd
1856  *
1857  * Wraps ipmi_lanplus_build_v2x_msg and returns a new entry object for the
1858  * command
1859  *
1860  */
1861 static struct ipmi_rq_entry *
ipmi_lanplus_build_v2x_ipmi_cmd(struct ipmi_intf * intf,struct ipmi_rq * req,int isRetry)1862 ipmi_lanplus_build_v2x_ipmi_cmd(
1863 								struct ipmi_intf * intf,
1864 								struct ipmi_rq * req,
1865 								int isRetry)
1866 {
1867 	struct ipmi_v2_payload v2_payload;
1868 	struct ipmi_rq_entry * entry;
1869 
1870 	/*
1871 	 * We have a problem.  we need to know the sequence number here,
1872 	 * because we use it in our stored entry.  But we also need to
1873 	 * know the sequence number when we generate our IPMI
1874 	 * representation far below.
1875 	 */
1876 	static uint8_t curr_seq = 0;
1877 
1878 	if( isRetry == 0 )
1879 		curr_seq += 1;
1880 
1881 	if (curr_seq >= 64)
1882 		curr_seq = 0;
1883 
1884 
1885 	/* IPMI Message Header -- Figure 13-4 of the IPMI v2.0 spec */
1886 	if ((intf->target_addr == intf->my_addr) || (!bridgePossible)) {
1887 		entry = ipmi_req_add_entry(intf, req, curr_seq);
1888 	/* it's a bridge command */
1889 	} else {
1890 		unsigned char backup_cmd;
1891 
1892 		/* Add entry for cmd */
1893 		entry = ipmi_req_add_entry(intf, req, curr_seq);
1894 
1895 		if (entry) {
1896 			entry->req.msg.target_cmd = entry->req.msg.cmd;
1897 			entry->req.msg.cmd = 0x34;
1898 
1899 			if (intf->transit_addr &&
1900 					intf->transit_addr != intf->my_addr)
1901 				entry->bridging_level = 2;
1902 			else
1903 				entry->bridging_level = 1;
1904 		}
1905 	}
1906 
1907 	if (entry == NULL)
1908 		return NULL;
1909 
1910 	// Build our payload
1911 	v2_payload.payload_type                 = IPMI_PAYLOAD_TYPE_IPMI;
1912 	v2_payload.payload_length               = req->msg.data_len + 7;
1913 	v2_payload.payload.ipmi_request.request = req;
1914 	v2_payload.payload.ipmi_request.rq_seq  = curr_seq;
1915 
1916 	ipmi_lanplus_build_v2x_msg(intf,                // in
1917 					&v2_payload,         // in
1918 					&(entry->msg_len),   // out
1919 					&(entry->msg_data),  // out
1920 					curr_seq); 		// in
1921 
1922 	return entry;
1923 }
1924 
1925 
1926 
1927 
1928 
1929 /*
1930  * IPMI LAN Request Message Format
1931  * +--------------------+
1932  * |  rmcp.ver          | 4 bytes
1933  * |  rmcp.__reserved   |
1934  * |  rmcp.seq          |
1935  * |  rmcp.class        |
1936  * +--------------------+
1937  * |  session.authtype  | 9 bytes
1938  * |  session.seq       |
1939  * |  session.id        |
1940  * +--------------------+
1941  * | [session.authcode] | 16 bytes (AUTHTYPE != none)
1942  * +--------------------+
1943  * |  message length    | 1 byte
1944  * +--------------------+
1945  * |  message.rs_addr   | 6 bytes
1946  * |  message.netfn_lun |
1947  * |  message.checksum  |
1948  * |  message.rq_addr   |
1949  * |  message.rq_seq    |
1950  * |  message.cmd       |
1951  * +--------------------+
1952  * | [request data]     | data_len bytes
1953  * +--------------------+
1954  * |  checksum          | 1 byte
1955  * +--------------------+
1956  */
1957 static struct ipmi_rq_entry *
ipmi_lanplus_build_v15_ipmi_cmd(struct ipmi_intf * intf,struct ipmi_rq * req)1958 ipmi_lanplus_build_v15_ipmi_cmd(
1959 								struct ipmi_intf * intf,
1960 								struct ipmi_rq * req)
1961 {
1962 	struct rmcp_hdr rmcp = {
1963 		.ver		= RMCP_VERSION_1,
1964 		.class		= RMCP_CLASS_IPMI,
1965 		.seq		= 0xff,
1966 	};
1967 	uint8_t * msg;
1968 	int cs, mp, len = 0, tmp;
1969 	struct ipmi_session  * session = intf->session;
1970 	struct ipmi_rq_entry * entry;
1971 
1972 	entry = ipmi_req_add_entry(intf, req, 0);
1973 	if (entry == NULL)
1974 		return NULL;
1975 
1976 	len = req->msg.data_len + 21;
1977 
1978 	msg = malloc(len);
1979 	if (msg == NULL) {
1980 		lprintf(LOG_ERR, "ipmitool: malloc failure");
1981 		return NULL;
1982 	}
1983 	memset(msg, 0, len);
1984 
1985 	/* rmcp header */
1986 	memcpy(msg, &rmcp, sizeof(rmcp));
1987 	len = sizeof(rmcp);
1988 
1989 	/*
1990 	 * ipmi session header
1991 	 */
1992 	/* Authtype should always be none for 1.5 packets sent from this
1993 	 * interface
1994 	 */
1995 	msg[len++] = IPMI_SESSION_AUTHTYPE_NONE;
1996 
1997 	msg[len++] = session->out_seq & 0xff;
1998 	msg[len++] = (session->out_seq >> 8) & 0xff;
1999 	msg[len++] = (session->out_seq >> 16) & 0xff;
2000 	msg[len++] = (session->out_seq >> 24) & 0xff;
2001 
2002 	/*
2003 	 * The session ID should be all zeroes for pre-session commands.  We
2004 	 * should only be using the 1.5 interface for the pre-session Get
2005 	 * Channel Authentication Capabilities command
2006 	 */
2007 	msg[len++] = 0;
2008 	msg[len++] = 0;
2009 	msg[len++] = 0;
2010 	msg[len++] = 0;
2011 
2012 	/* message length */
2013 	msg[len++] = req->msg.data_len + 7;
2014 
2015 	/* ipmi message header */
2016 	cs = mp = len;
2017 	msg[len++] = IPMI_BMC_SLAVE_ADDR;
2018 	msg[len++] = req->msg.netfn << 2;
2019 	tmp = len - cs;
2020 	msg[len++] = ipmi_csum(msg+cs, tmp);
2021 	cs = len;
2022 	msg[len++] = IPMI_REMOTE_SWID;
2023 
2024 	entry->rq_seq = 0;
2025 
2026 	msg[len++] = entry->rq_seq << 2;
2027 	msg[len++] = req->msg.cmd;
2028 
2029 	lprintf(LOG_DEBUG+1, ">> IPMI Request Session Header");
2030 	lprintf(LOG_DEBUG+1, ">>   Authtype   : %s",
2031 		val2str(IPMI_SESSION_AUTHTYPE_NONE, ipmi_authtype_session_vals));
2032 	lprintf(LOG_DEBUG+1, ">>   Sequence   : 0x%08lx",
2033 		(long)session->out_seq);
2034 	lprintf(LOG_DEBUG+1, ">>   Session ID : 0x%08lx",
2035 		(long)0);
2036 
2037 	lprintf(LOG_DEBUG+1, ">> IPMI Request Message Header");
2038 	lprintf(LOG_DEBUG+1, ">>   Rs Addr    : %02x", IPMI_BMC_SLAVE_ADDR);
2039 	lprintf(LOG_DEBUG+1, ">>   NetFn      : %02x", req->msg.netfn);
2040 	lprintf(LOG_DEBUG+1, ">>   Rs LUN     : %01x", 0);
2041 	lprintf(LOG_DEBUG+1, ">>   Rq Addr    : %02x", IPMI_REMOTE_SWID);
2042 	lprintf(LOG_DEBUG+1, ">>   Rq Seq     : %02x", entry->rq_seq);
2043 	lprintf(LOG_DEBUG+1, ">>   Rq Lun     : %01x", 0);
2044 	lprintf(LOG_DEBUG+1, ">>   Command    : %02x", req->msg.cmd);
2045 
2046 	/* message data */
2047 	if (req->msg.data_len) {
2048 		memcpy(msg+len, req->msg.data, req->msg.data_len);
2049 		len += req->msg.data_len;
2050 	}
2051 
2052 	/* second checksum */
2053 	tmp = len - cs;
2054 	msg[len++] = ipmi_csum(msg+cs, tmp);
2055 
2056 	entry->msg_len = len;
2057 	entry->msg_data = msg;
2058 
2059 	return entry;
2060 }
2061 
2062 
2063 
2064 /*
2065  * is_sol_packet
2066  */
2067 static int
is_sol_packet(struct ipmi_rs * rsp)2068 is_sol_packet(struct ipmi_rs * rsp)
2069 {
2070 	return (rsp                                                           &&
2071 			(rsp->session.authtype    == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
2072 			(rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL));
2073 }
2074 
2075 
2076 
2077 /*
2078  * sol_response_acks_packet
2079  */
2080 static int
sol_response_acks_packet(struct ipmi_rs * rsp,struct ipmi_v2_payload * payload)2081 sol_response_acks_packet(
2082 						 struct ipmi_rs         * rsp,
2083 						 struct ipmi_v2_payload * payload)
2084 {
2085 	return (is_sol_packet(rsp)                                            &&
2086 			payload                                                       &&
2087 			(payload->payload_type    == IPMI_PAYLOAD_TYPE_SOL)           &&
2088 			(rsp->payload.sol_packet.acked_packet_number ==
2089 			 payload->payload.sol_packet.packet_sequence_number));
2090 }
2091 
2092 
2093 
2094 /*
2095  * ipmi_lanplus_send_payload
2096  *
2097  */
2098 struct ipmi_rs *
ipmi_lanplus_send_payload(struct ipmi_intf * intf,struct ipmi_v2_payload * payload)2099 ipmi_lanplus_send_payload(
2100 						  struct ipmi_intf * intf,
2101 						  struct ipmi_v2_payload * payload)
2102 {
2103 	struct ipmi_rs      * rsp = NULL;
2104 	uint8_t             * msg_data;
2105 	int                   msg_length;
2106 	struct ipmi_session * session = intf->session;
2107 	struct ipmi_rq_entry * entry = NULL;
2108 	int                   try = 0;
2109 	int                   xmit = 1;
2110 	time_t                ltime;
2111 	uint32_t	      saved_timeout;
2112 
2113 	if (!intf->opened && intf->open && intf->open(intf) < 0)
2114 		return NULL;
2115 
2116 	/*
2117 	 * The session timeout is initialized in the above interface open,
2118 	 * so it will only be valid after the open completes.
2119 	 */
2120 	saved_timeout = session->timeout;
2121 	while (try < intf->ssn_params.retry) {
2122 		//ltime = time(NULL);
2123 
2124 		if (xmit) {
2125 			ltime = time(NULL);
2126 
2127 			if (payload->payload_type == IPMI_PAYLOAD_TYPE_IPMI)
2128 			{
2129 				/*
2130 				 * Build an IPMI v1.5 or v2 command
2131 				 */
2132 				struct ipmi_rq * ipmi_request = payload->payload.ipmi_request.request;
2133 
2134 				lprintf(LOG_DEBUG, "");
2135 				lprintf(LOG_DEBUG, ">> Sending IPMI command payload");
2136 				lprintf(LOG_DEBUG, ">>    netfn   : 0x%02x", ipmi_request->msg.netfn);
2137 				lprintf(LOG_DEBUG, ">>    command : 0x%02x", ipmi_request->msg.cmd);
2138 
2139 				if (verbose > 1)
2140 				{
2141 					uint16_t i;
2142 					fprintf(stderr, ">>    data    : ");
2143 					for (i = 0; i < ipmi_request->msg.data_len; ++i)
2144 						fprintf(stderr, "0x%02x ", ipmi_request->msg.data[i]);
2145 					fprintf(stderr, "\n\n");
2146 				}
2147 
2148 
2149 				/*
2150 				 * If we are presession, and the command is GET CHANNEL AUTHENTICATION
2151 				 * CAPABILITIES, we will build the command in v1.5 format.  This is so
2152 				 * that we can ask any server whether it supports IPMI v2 / RMCP+
2153 				 * before we attempt to open a v2.x session.
2154 				 */
2155 				if ((ipmi_request->msg.netfn == IPMI_NETFN_APP) &&
2156 					 (ipmi_request->msg.cmd   == IPMI_GET_CHANNEL_AUTH_CAP) &&
2157 					 (session->v2_data.bmc_id  == 0)) // jme - check
2158 				{
2159 					lprintf(LOG_DEBUG+1, "BUILDING A v1.5 COMMAND");
2160 					entry = ipmi_lanplus_build_v15_ipmi_cmd(intf, ipmi_request);
2161 				}
2162 				else
2163 				{
2164 					int isRetry = ( try > 0 ? 1 : 0 );
2165 
2166 					lprintf(LOG_DEBUG+1, "BUILDING A v2 COMMAND");
2167 					entry = ipmi_lanplus_build_v2x_ipmi_cmd(intf, ipmi_request, isRetry);
2168 				}
2169 
2170 				if (entry == NULL) {
2171 					lprintf(LOG_ERR, "Aborting send command, unable to build");
2172 					return NULL;
2173 				}
2174 
2175 				msg_data   = entry->msg_data;
2176 				msg_length = entry->msg_len;
2177 			}
2178 
2179 			else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST)
2180 			{
2181 				lprintf(LOG_DEBUG, ">> SENDING AN OPEN SESSION REQUEST\n");
2182 				assert(session->v2_data.session_state == LANPLUS_STATE_PRESESSION
2183 						|| session->v2_data.session_state == LANPLUS_STATE_OPEN_SESSION_SENT);
2184 
2185 				ipmi_lanplus_build_v2x_msg(intf,        /* in  */
2186 								payload,     /* in  */
2187 								&msg_length, /* out */
2188 								&msg_data,   /* out */
2189 								0);  /* irrelevant for this msg*/
2190 
2191 			}
2192 
2193 			else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RAKP_1)
2194 			{
2195 				lprintf(LOG_DEBUG, ">> SENDING A RAKP 1 MESSAGE\n");
2196 				assert(session->v2_data.session_state ==
2197 						 LANPLUS_STATE_OPEN_SESSION_RECEIEVED);
2198 
2199 				ipmi_lanplus_build_v2x_msg(intf,        /* in  */
2200 								payload,     /* in  */
2201 								&msg_length, /* out */
2202 								&msg_data,   /* out */
2203 								0);  /* irrelevant for this msg*/
2204 
2205 			}
2206 
2207 			else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RAKP_3)
2208 			{
2209 				lprintf(LOG_DEBUG, ">> SENDING A RAKP 3 MESSAGE\n");
2210 				assert(session->v2_data.session_state ==
2211 						 LANPLUS_STATE_RAKP_2_RECEIVED);
2212 
2213 				ipmi_lanplus_build_v2x_msg(intf,        /* in  */
2214 								payload,     /* in  */
2215 								&msg_length, /* out */
2216 								&msg_data,   /* out */
2217 								0);  /* irrelevant for this msg*/
2218 
2219 			}
2220 
2221 			else if (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL)
2222 			{
2223 				lprintf(LOG_DEBUG, ">> SENDING A SOL MESSAGE\n");
2224 				assert(session->v2_data.session_state == LANPLUS_STATE_ACTIVE);
2225 
2226 				ipmi_lanplus_build_v2x_msg(intf,        /* in  */
2227 								payload,     /* in  */
2228 								&msg_length, /* out */
2229 								&msg_data,   /* out */
2230 								0);  /* irrelevant for this msg*/
2231 			}
2232 
2233 			else
2234 			{
2235 				lprintf(LOG_ERR, "Payload type 0x%0x is unsupported!",
2236 					payload->payload_type);
2237 				assert(0);
2238 			}
2239 
2240 
2241 			if (ipmi_lan_send_packet(intf, msg_data, msg_length) < 0) {
2242 				lprintf(LOG_ERR, "IPMI LAN send command failed");
2243 				return NULL;
2244 			}
2245 		}
2246 
2247 		/* if we are set to noanswer we do not expect response */
2248 		if (intf->noanswer)
2249 			break;
2250 
2251 		usleep(100); 			/* Not sure what this is for */
2252 
2253 		/* Remember our connection state */
2254 		switch (payload->payload_type)
2255 		{
2256 		case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST:
2257 			session->v2_data.session_state = LANPLUS_STATE_OPEN_SESSION_SENT;
2258 			/* not retryable for timeouts, force no retry */
2259 			try = intf->ssn_params.retry;
2260 			break;
2261 		case IPMI_PAYLOAD_TYPE_RAKP_1:
2262 			session->v2_data.session_state = LANPLUS_STATE_RAKP_1_SENT;
2263 			/* not retryable for timeouts, force no retry */
2264 			try = intf->ssn_params.retry;
2265 			break;
2266 		case IPMI_PAYLOAD_TYPE_RAKP_3:
2267 			/* not retryable for timeouts, force no retry */
2268 			try = intf->ssn_params.retry;
2269 			session->v2_data.session_state = LANPLUS_STATE_RAKP_3_SENT;
2270 			break;
2271 		}
2272 
2273 
2274 		/*
2275 		 * Special case for SOL outbound packets.
2276 		 */
2277 		if (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL)
2278 		{
2279 			if (! payload->payload.sol_packet.packet_sequence_number)
2280 			{
2281 				/* We're just sending an ACK.  No need to retry. */
2282 				break;
2283 			}
2284 
2285 
2286 			rsp = ipmi_lanplus_recv_sol(intf); /* Grab the next packet */
2287 
2288 			if (sol_response_acks_packet(rsp, payload))
2289 				break;
2290 
2291 			else if (is_sol_packet(rsp) && rsp->data_len)
2292 			{
2293 				/*
2294 				 * We're still waiting for our ACK, but we more data from
2295 				 * the BMC
2296 				 */
2297 				intf->session->sol_data.sol_input_handler(rsp);
2298 				/* In order to avoid duplicate output, just set data_len to 0 */
2299 				rsp->data_len = 0;
2300 			}
2301 		}
2302 
2303 
2304 		/* Non-SOL processing */
2305 		else
2306 		{
2307 			rsp = ipmi_lan_poll_recv(intf);
2308 
2309 			/* Duplicate Request ccode most likely indicates a response to
2310 			   a previous retry. Ignore and keep polling. */
2311 			while ((rsp != NULL) && (rsp->ccode == 0xcf))
2312 			{
2313 				rsp = NULL;
2314 				rsp = ipmi_lan_poll_recv(intf);
2315 			}
2316 
2317 			if (rsp)
2318 				break;
2319 			/* This payload type is retryable for timeouts. */
2320 			if ((payload->payload_type == IPMI_PAYLOAD_TYPE_IPMI) && entry) {
2321 				ipmi_req_remove_entry( entry->rq_seq, entry->req.msg.cmd);
2322 			}
2323 		}
2324 
2325 		/* only timeout if time exceeds the timeout value */
2326 		xmit = ((time(NULL) - ltime) >= session->timeout);
2327 
2328 		usleep(5000);
2329 
2330 		if (xmit) {
2331 			/* increment session timeout by 1 second each retry */
2332 			session->timeout++;
2333 		}
2334 
2335 		try++;
2336 	}
2337 	session->timeout = saved_timeout;
2338 
2339 	/* IPMI messages are deleted under ipmi_lan_poll_recv() */
2340 	switch (payload->payload_type) {
2341 	case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST:
2342 	case IPMI_PAYLOAD_TYPE_RAKP_1:
2343 	case IPMI_PAYLOAD_TYPE_RAKP_3:
2344 		free(msg_data);
2345 		msg_data = NULL;
2346 		break;
2347 	}
2348 
2349 	return rsp;
2350 }
2351 
2352 
2353 
2354 /*
2355  * is_sol_partial_ack
2356  *
2357  * Determine if the response is a partial ACK/NACK that indicates
2358  * we need to resend part of our packet.
2359  *
2360  * returns the number of characters we need to resend, or
2361  *         0 if this isn't an ACK or we don't need to resend anything
2362  */
is_sol_partial_ack(struct ipmi_intf * intf,struct ipmi_v2_payload * v2_payload,struct ipmi_rs * rs)2363 int is_sol_partial_ack(
2364 						struct ipmi_intf       * intf,
2365 						struct ipmi_v2_payload * v2_payload,
2366 						struct ipmi_rs         * rs)
2367 {
2368 	int chars_to_resend = 0;
2369 
2370 	if (v2_payload                               &&
2371 		rs                                       &&
2372 		is_sol_packet(rs)                        &&
2373 		sol_response_acks_packet(rs, v2_payload) &&
2374 		(rs->payload.sol_packet.accepted_character_count <
2375 		 v2_payload->payload.sol_packet.character_count))
2376 	{
2377 		if (ipmi_oem_active(intf, "intelplus") &&
2378 			 rs->payload.sol_packet.accepted_character_count == 0)
2379 			return 0;
2380 
2381 		chars_to_resend =
2382 			v2_payload->payload.sol_packet.character_count -
2383 			rs->payload.sol_packet.accepted_character_count;
2384 	}
2385 
2386 	return chars_to_resend;
2387 }
2388 
2389 
2390 
2391 /*
2392  * set_sol_packet_sequence_number
2393  */
set_sol_packet_sequence_number(struct ipmi_intf * intf,struct ipmi_v2_payload * v2_payload)2394 static void set_sol_packet_sequence_number(
2395 											struct ipmi_intf * intf,
2396 											struct ipmi_v2_payload * v2_payload)
2397 {
2398 	/* Keep our sequence number sane */
2399 	if (intf->session->sol_data.sequence_number > 0x0F)
2400 		intf->session->sol_data.sequence_number = 1;
2401 
2402 	v2_payload->payload.sol_packet.packet_sequence_number =
2403 		intf->session->sol_data.sequence_number++;
2404 }
2405 
2406 
2407 
2408 /*
2409  * ipmi_lanplus_send_sol
2410  *
2411  * Sends a SOL packet..  We handle partial ACK/NACKs from the BMC here.
2412  *
2413  * Returns a pointer to the SOL ACK we received, or
2414  *         0 on failure
2415  *
2416  */
2417 struct ipmi_rs *
ipmi_lanplus_send_sol(struct ipmi_intf * intf,struct ipmi_v2_payload * v2_payload)2418 ipmi_lanplus_send_sol(
2419 					  struct ipmi_intf * intf,
2420 					  struct ipmi_v2_payload * v2_payload)
2421 {
2422 	struct ipmi_rs * rs;
2423 
2424 	/*
2425 	 * chars_to_resend indicates either that we got a NACK telling us
2426 	 * that we need to resend some part of our data.
2427 	 */
2428 	int chars_to_resend = 0;
2429 
2430 	v2_payload->payload_type   = IPMI_PAYLOAD_TYPE_SOL;
2431 
2432 	/*
2433 	 * Payload length is just the length of the character
2434 	 * data here.
2435 	 */
2436 	v2_payload->payload_length = v2_payload->payload.sol_packet.character_count;
2437 
2438 	v2_payload->payload.sol_packet.acked_packet_number = 0; /* NA */
2439 
2440 	set_sol_packet_sequence_number(intf, v2_payload);
2441 
2442 	v2_payload->payload.sol_packet.accepted_character_count = 0; /* NA */
2443 
2444 	rs = ipmi_lanplus_send_payload(intf, v2_payload);
2445 
2446 	/* Determine if we need to resend some of our data */
2447 	chars_to_resend = is_sol_partial_ack(intf, v2_payload, rs);
2448 
2449 	while (rs && !rs->payload.sol_packet.transfer_unavailable &&
2450 			 !rs->payload.sol_packet.is_nack &&
2451 			 chars_to_resend)
2452 	{
2453 		/*
2454 		 * We first need to handle any new data we might have
2455 		 * received in our NACK
2456 		 */
2457 		if (rs->data_len)
2458 			intf->session->sol_data.sol_input_handler(rs);
2459 
2460 		set_sol_packet_sequence_number(intf, v2_payload);
2461 
2462 		/* Just send the required data */
2463 		memmove(v2_payload->payload.sol_packet.data,
2464 				v2_payload->payload.sol_packet.data +
2465 				rs->payload.sol_packet.accepted_character_count,
2466 				chars_to_resend);
2467 
2468 		v2_payload->payload.sol_packet.character_count = chars_to_resend;
2469 
2470 		v2_payload->payload_length = v2_payload->payload.sol_packet.character_count;
2471 
2472 		rs = ipmi_lanplus_send_payload(intf, v2_payload);
2473 
2474 		chars_to_resend = is_sol_partial_ack(intf, v2_payload, rs);
2475 	}
2476 
2477 	return rs;
2478 }
2479 
2480 
2481 
2482 /*
2483  * check_sol_packet_for_new_data
2484  *
2485  * Determine whether the SOL packet has already been seen
2486  * and whether the packet has new data for us.
2487  *
2488  * This function has the side effect of removing an previously
2489  * seen data, and moving new data to the front.
2490  *
2491  * It also "Remembers" the data so we don't get repeats.
2492  *
2493  * returns the number of new bytes in the SOL packet
2494  */
2495 static int
check_sol_packet_for_new_data(struct ipmi_intf * intf,struct ipmi_rs * rsp)2496 check_sol_packet_for_new_data(
2497 							  struct ipmi_intf * intf,
2498 							  struct ipmi_rs *rsp)
2499 {
2500 	static uint8_t last_received_sequence_number = 0;
2501 	static uint8_t last_received_byte_count      = 0;
2502 	int new_data_size                                  = 0;
2503 
2504 
2505 	if (rsp &&
2506 		(rsp->session.authtype    == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
2507 		(rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL))
2508 	{
2509 		/* Store the data length before we mod it */
2510 		uint8_t unaltered_data_len = rsp->data_len;
2511 
2512 		if (rsp->payload.sol_packet.packet_sequence_number ==
2513 			last_received_sequence_number)
2514 		{
2515 
2516 			/*
2517 			 * This is the same as the last packet, but may include
2518 			 * extra data
2519 			 */
2520 			new_data_size = rsp->data_len - last_received_byte_count;
2521 
2522 			if (new_data_size > 0)
2523 			{
2524 				/* We have more data to process */
2525 				memmove(rsp->data,
2526 						rsp->data +
2527 						rsp->data_len - new_data_size,
2528 						new_data_size);
2529 			}
2530 
2531 			rsp->data_len = new_data_size;
2532 		}
2533 
2534 
2535 		/*
2536 		 *Rember the data for next round
2537 		 */
2538 		if (rsp->payload.sol_packet.packet_sequence_number)
2539 		{
2540 			last_received_sequence_number =
2541 				rsp->payload.sol_packet.packet_sequence_number;
2542 
2543 			last_received_byte_count = unaltered_data_len;
2544 		}
2545 	}
2546 
2547 
2548 	return new_data_size;
2549 }
2550 
2551 
2552 
2553 /*
2554  * ack_sol_packet
2555  *
2556  * Provided the specified packet looks reasonable, ACK it.
2557  */
2558 static void
ack_sol_packet(struct ipmi_intf * intf,struct ipmi_rs * rsp)2559 ack_sol_packet(
2560 				struct ipmi_intf * intf,
2561 				struct ipmi_rs * rsp)
2562 {
2563 	if (rsp                                                           &&
2564 		(rsp->session.authtype    == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
2565 		(rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL)           &&
2566 		(rsp->payload.sol_packet.packet_sequence_number))
2567 	{
2568 		struct ipmi_v2_payload ack;
2569 
2570 		memset(&ack, 0, sizeof(struct ipmi_v2_payload));
2571 
2572 		ack.payload_type   = IPMI_PAYLOAD_TYPE_SOL;
2573 
2574 		/*
2575 		 * Payload length is just the length of the character
2576 		 * data here.
2577 		 */
2578 		ack.payload_length = 0;
2579 
2580 		/* ACK packets have sequence numbers of 0 */
2581 		ack.payload.sol_packet.packet_sequence_number = 0;
2582 
2583 		ack.payload.sol_packet.acked_packet_number =
2584 			rsp->payload.sol_packet.packet_sequence_number;
2585 
2586 		ack.payload.sol_packet.accepted_character_count = rsp->data_len;
2587 
2588 		ipmi_lanplus_send_payload(intf, &ack);
2589 	}
2590 }
2591 
2592 
2593 
2594 /*
2595  * ipmi_lanplus_recv_sol
2596  *
2597  * Receive a SOL packet and send an ACK in response.
2598  *
2599  */
2600 struct ipmi_rs *
ipmi_lanplus_recv_sol(struct ipmi_intf * intf)2601 ipmi_lanplus_recv_sol(struct ipmi_intf * intf)
2602 {
2603 	struct ipmi_rs * rsp = ipmi_lan_poll_recv(intf);
2604 
2605 	if (rsp && rsp->session.authtype != 0)
2606 	{
2607 		ack_sol_packet(intf, rsp);
2608 
2609 		/*
2610 		 * Remembers the data sent, and alters the data to just
2611 		 * include the new stuff.
2612 		 */
2613 		check_sol_packet_for_new_data(intf, rsp);
2614 	}
2615 	return rsp;
2616 }
2617 
2618 
2619 
2620 /**
2621  * ipmi_lanplus_send_ipmi_cmd
2622  *
2623  * Build a payload request and dispatch it.
2624  */
2625 struct ipmi_rs *
ipmi_lanplus_send_ipmi_cmd(struct ipmi_intf * intf,struct ipmi_rq * req)2626 ipmi_lanplus_send_ipmi_cmd(
2627 							struct ipmi_intf * intf,
2628 							struct ipmi_rq * req)
2629 {
2630 	struct ipmi_v2_payload v2_payload;
2631 
2632 	v2_payload.payload_type = IPMI_PAYLOAD_TYPE_IPMI;
2633 	v2_payload.payload.ipmi_request.request = req;
2634 
2635 	return ipmi_lanplus_send_payload(intf, &v2_payload);
2636 }
2637 
2638 
2639 /*
2640  * ipmi_get_auth_capabilities_cmd
2641  *
2642  * This command may have to be sent twice.  We first ask for the
2643  * authentication capabilities with the "request IPMI v2 data bit"
2644  * set.  If this fails, we send the same command without that bit
2645  * set.
2646  *
2647  * param intf is the initialized (but possibly) pre-session interface
2648  *       on which we will send the command
2649  * param auth_cap [out] will be initialized to hold the Get Channel
2650  *       Authentication Capabilities return data on success.  Its
2651  *       contents will be undefined on error.
2652  *
2653  * returns 0 on success
2654  *         non-zero if we were unable to contact the BMC, or we cannot
2655  *         get a successful response
2656  *
2657  */
2658 static int
ipmi_get_auth_capabilities_cmd(struct ipmi_intf * intf,struct get_channel_auth_cap_rsp * auth_cap)2659 ipmi_get_auth_capabilities_cmd(
2660 								struct ipmi_intf * intf,
2661 								struct get_channel_auth_cap_rsp * auth_cap)
2662 {
2663 	struct ipmi_rs * rsp;
2664 	struct ipmi_rq req;
2665 	uint8_t msg_data[2];
2666 	uint8_t backupBridgePossible;
2667 
2668 	backupBridgePossible = bridgePossible;
2669 
2670 	bridgePossible = 0;
2671 
2672 	msg_data[0] = IPMI_LAN_CHANNEL_E | 0x80; // Ask for IPMI v2 data as well
2673 	msg_data[1] = intf->ssn_params.privlvl;
2674 
2675 	memset(&req, 0, sizeof(req));
2676 	req.msg.netfn    = IPMI_NETFN_APP;            // 0x06
2677 	req.msg.cmd      = IPMI_GET_CHANNEL_AUTH_CAP; // 0x38
2678 	req.msg.data     = msg_data;
2679 	req.msg.data_len = 2;
2680 
2681 	rsp = intf->sendrecv(intf, &req);
2682 
2683 	if (rsp == NULL || rsp->ccode > 0) {
2684 		/*
2685 		 * It's very possible that this failed because we asked for IPMI
2686 		 * v2 data. Ask again, without requesting IPMI v2 data.
2687 		 */
2688 		msg_data[0] &= 0x7F;
2689 
2690 		rsp = intf->sendrecv(intf, &req);
2691 
2692 		if (rsp == NULL) {
2693 			lprintf(LOG_INFO, "Get Auth Capabilities error");
2694 			return 1;
2695 		}
2696 		if (rsp->ccode > 0) {
2697 			lprintf(LOG_INFO, "Get Auth Capabilities error: %s",
2698 				val2str(rsp->ccode, completion_code_vals));
2699 			return 1;
2700 		}
2701 	}
2702 
2703 
2704 	memcpy(auth_cap,
2705 			rsp->data,
2706 			sizeof(struct get_channel_auth_cap_rsp));
2707 
2708 	bridgePossible = backupBridgePossible;
2709 
2710 	return 0;
2711 }
2712 
2713 
2714 
2715 static int
ipmi_close_session_cmd(struct ipmi_intf * intf)2716 ipmi_close_session_cmd(struct ipmi_intf * intf)
2717 {
2718 	struct ipmi_rs * rsp;
2719 	struct ipmi_rq req;
2720 	uint8_t msg_data[4];
2721 	uint32_t bmc_session_lsbf;
2722 	uint8_t backupBridgePossible;
2723 
2724 	if (intf->session == NULL
2725 			|| intf->session->v2_data.session_state != LANPLUS_STATE_ACTIVE)
2726 		return -1;
2727 
2728 	backupBridgePossible = bridgePossible;
2729 
2730 	intf->target_addr = IPMI_BMC_SLAVE_ADDR;
2731 	bridgePossible = 0;
2732 
2733 	bmc_session_lsbf = intf->session->v2_data.bmc_id;
2734 #if WORDS_BIGENDIAN
2735 	bmc_session_lsbf = BSWAP_32(bmc_session_lsbf);
2736 #endif
2737 
2738 	memcpy(&msg_data, &bmc_session_lsbf, 4);
2739 
2740 	memset(&req, 0, sizeof(req));
2741 	req.msg.netfn		= IPMI_NETFN_APP;
2742 	req.msg.cmd		    = 0x3c;
2743 	req.msg.data		= msg_data;
2744 	req.msg.data_len	= 4;
2745 
2746 	rsp = intf->sendrecv(intf, &req);
2747 	if (rsp == NULL) {
2748 		/* Looks like the session was closed */
2749 		lprintf(LOG_ERR, "Close Session command failed");
2750 		return -1;
2751 	}
2752 	if (verbose > 2)
2753 		printbuf(rsp->data, rsp->data_len, "close_session");
2754 
2755 	if (rsp->ccode == 0x87) {
2756 		lprintf(LOG_ERR, "Failed to Close Session: invalid "
2757 			"session ID %08lx",
2758 			(long)intf->session->v2_data.bmc_id);
2759 		return -1;
2760 	}
2761 	if (rsp->ccode > 0) {
2762 		lprintf(LOG_ERR, "Close Session command failed: %s",
2763 			val2str(rsp->ccode, completion_code_vals));
2764 		return -1;
2765 	}
2766 
2767 	lprintf(LOG_DEBUG, "Closed Session %08lx\n",
2768 		(long)intf->session->v2_data.bmc_id);
2769 
2770 	bridgePossible = backupBridgePossible;
2771 
2772 	return 0;
2773 }
2774 
2775 
2776 
2777 /*
2778  * ipmi_lanplus_open_session
2779  *
2780  * Build and send the open session command.  See section 13.17 of the IPMI
2781  * v2 specification for details.
2782  */
2783 static int
ipmi_lanplus_open_session(struct ipmi_intf * intf)2784 ipmi_lanplus_open_session(struct ipmi_intf * intf)
2785 {
2786 	struct ipmi_v2_payload v2_payload;
2787 	struct ipmi_session * session = intf->session;
2788 	uint8_t * msg;
2789 	struct ipmi_rs * rsp;
2790 	/* 0 = success, 1 = error, 2 = timeout */
2791 	int rc = 0;
2792 
2793 
2794 	/*
2795 	 * Build an Open Session Request Payload
2796 	 */
2797 	msg = (uint8_t*)malloc(IPMI_OPEN_SESSION_REQUEST_SIZE);
2798 	if (msg == NULL) {
2799 		lprintf(LOG_ERR, "ipmitool: malloc failure");
2800 		return 1;
2801 	}
2802 
2803 	memset(msg, 0, IPMI_OPEN_SESSION_REQUEST_SIZE);
2804 
2805 	msg[0] = 0; /* Message tag */
2806 	if (ipmi_oem_active(intf, "intelplus") || intf->ssn_params.privlvl != IPMI_SESSION_PRIV_ADMIN)
2807 		msg[1] = intf->ssn_params.privlvl;
2808 	else
2809 		msg[1] = 0; /* Give us highest privlg level based on supported algorithms */
2810 	msg[2] = 0; /* reserved */
2811 	msg[3] = 0; /* reserved */
2812 
2813 	/* Choose our session ID for easy recognition in the packet dump */
2814 	session->v2_data.console_id = 0xA0A2A3A4;
2815 	msg[4] = session->v2_data.console_id & 0xff;
2816 	msg[5] = (session->v2_data.console_id >> 8)  & 0xff;
2817 	msg[6] = (session->v2_data.console_id >> 16) & 0xff;
2818 	msg[7] = (session->v2_data.console_id >> 24) & 0xff;
2819 
2820 
2821 	if (lanplus_get_requested_ciphers(intf->ssn_params.cipher_suite_id,
2822 									  &(session->v2_data.requested_auth_alg),
2823 									  &(session->v2_data.requested_integrity_alg),
2824 									  &(session->v2_data.requested_crypt_alg)))
2825 	{
2826 		lprintf(LOG_WARNING, "Unsupported cipher suite ID : %d\n",
2827 				intf->ssn_params.cipher_suite_id);
2828 		free(msg);
2829 		msg = NULL;
2830 		return 1;
2831 	}
2832 
2833 
2834 	/*
2835 	 * Authentication payload
2836 	 */
2837 	msg[8]  = 0; /* specifies authentication payload */
2838 	msg[9]  = 0; /* reserved */
2839 	msg[10] = 0; /* reserved */
2840 	msg[11] = 8; /* payload length */
2841 	msg[12] = session->v2_data.requested_auth_alg;
2842 	msg[13] = 0; /* reserved */
2843 	msg[14] = 0; /* reserved */
2844 	msg[15] = 0; /* reserved */
2845 
2846 	/*
2847 	 * Integrity payload
2848 	 */
2849 	msg[16] = 1; /* specifies integrity payload */
2850 	msg[17] = 0; /* reserved */
2851 	msg[18] = 0; /* reserved */
2852 	msg[19] = 8; /* payload length */
2853 	msg[20] = session->v2_data.requested_integrity_alg;
2854 	msg[21] = 0; /* reserved */
2855 	msg[22] = 0; /* reserved */
2856 	msg[23] = 0; /* reserved */
2857 
2858 	/*
2859 	 * Confidentiality/Encryption payload
2860 	 */
2861 	msg[24] = 2; /* specifies confidentiality payload */
2862 	msg[25] = 0; /* reserved */
2863 	msg[26] = 0; /* reserved */
2864 	msg[27] = 8; /* payload length */
2865 	msg[28] = session->v2_data.requested_crypt_alg;
2866 	msg[29] = 0; /* reserved */
2867 	msg[30] = 0; /* reserved */
2868 	msg[31] = 0; /* reserved */
2869 
2870 
2871 	v2_payload.payload_type   = IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST;
2872 	v2_payload.payload_length = IPMI_OPEN_SESSION_REQUEST_SIZE;
2873 	v2_payload.payload.open_session_request.request = msg;
2874 
2875 	rsp = ipmi_lanplus_send_payload(intf, &v2_payload);
2876 
2877 	free(msg);
2878 	msg = NULL;
2879 	if (rsp == NULL ) {
2880 		lprintf(LOG_DEBUG, "Timeout in open session response message.");
2881 		return 2;
2882 	}
2883 	if (verbose)
2884 		lanplus_dump_open_session_response(rsp);
2885 
2886 	if (rsp->payload.open_session_response.rakp_return_code !=
2887 		IPMI_RAKP_STATUS_NO_ERRORS)
2888 	{
2889 		lprintf(LOG_WARNING, "Error in open session response message : %s\n",
2890 			val2str(rsp->payload.open_session_response.rakp_return_code,
2891 				ipmi_rakp_return_codes));
2892 		return 1;
2893 	}
2894 	else
2895 	{
2896 		if (rsp->payload.open_session_response.console_id !=
2897 			 session->v2_data.console_id) {
2898 			lprintf(LOG_WARNING, "Warning: Console session ID is not "
2899 				"what we requested");
2900 		}
2901 
2902 		session->v2_data.max_priv_level =
2903 			rsp->payload.open_session_response.max_priv_level;
2904 		session->v2_data.bmc_id         =
2905 			rsp->payload.open_session_response.bmc_id;
2906 		session->v2_data.auth_alg       =
2907 			rsp->payload.open_session_response.auth_alg;
2908 		session->v2_data.integrity_alg  =
2909 			rsp->payload.open_session_response.integrity_alg;
2910 		session->v2_data.crypt_alg      =
2911 			rsp->payload.open_session_response.crypt_alg;
2912 		session->v2_data.session_state  =
2913 			LANPLUS_STATE_OPEN_SESSION_RECEIEVED;
2914 
2915 
2916 		/*
2917 		 * Verify that we have agreed on a cipher suite
2918 		 */
2919 		if (rsp->payload.open_session_response.auth_alg !=
2920 			session->v2_data.requested_auth_alg)
2921 		{
2922 			lprintf(LOG_WARNING, "Authentication algorithm 0x%02x is "
2923 					"not what we requested 0x%02x\n",
2924 					rsp->payload.open_session_response.auth_alg,
2925 					session->v2_data.requested_auth_alg);
2926 			rc = 1;
2927 		}
2928 		else if (rsp->payload.open_session_response.integrity_alg !=
2929 				 session->v2_data.requested_integrity_alg)
2930 		{
2931 			lprintf(LOG_WARNING, "Integrity algorithm 0x%02x is "
2932 					"not what we requested 0x%02x\n",
2933 					rsp->payload.open_session_response.integrity_alg,
2934 					session->v2_data.requested_integrity_alg);
2935 			rc = 1;
2936 		}
2937 		else if (rsp->payload.open_session_response.crypt_alg !=
2938 				 session->v2_data.requested_crypt_alg)
2939 		{
2940 			lprintf(LOG_WARNING, "Encryption algorithm 0x%02x is "
2941 					"not what we requested 0x%02x\n",
2942 					rsp->payload.open_session_response.crypt_alg,
2943 					session->v2_data.requested_crypt_alg);
2944 			rc = 1;
2945 		}
2946 
2947 	}
2948 
2949 	return rc;
2950 }
2951 
2952 
2953 
2954 /*
2955  * ipmi_lanplus_rakp1
2956  *
2957  * Build and send the RAKP 1 message as part of the IPMI v2 / RMCP+ session
2958  * negotiation protocol.  We also read and validate the RAKP 2 message received
2959  * from the BMC, here.  See section 13.20 of the IPMI v2 specification for
2960  * details.
2961  *
2962  * returns 0 on success
2963  *         1 on failure
2964  *
2965  * Note that failure is only indicated if we have an internal error of
2966  * some kind. If we actually get a RAKP 2 message in response to our
2967  * RAKP 1 message, any errors will be stored in
2968  * session->v2_data.rakp2_return_code and sent to the BMC in the RAKP
2969  * 3 message.
2970  */
2971 static int
ipmi_lanplus_rakp1(struct ipmi_intf * intf)2972 ipmi_lanplus_rakp1(struct ipmi_intf * intf)
2973 {
2974 	struct ipmi_v2_payload v2_payload;
2975 	struct ipmi_session * session = intf->session;
2976 	uint8_t * msg;
2977 	struct ipmi_rs * rsp;
2978 	int rc = 0;    /* 0 = success, 1 = error, 2 = timeout */
2979 
2980 	/*
2981 	 * Build a RAKP 1 message
2982 	 */
2983 	msg = (uint8_t*)malloc(IPMI_RAKP1_MESSAGE_SIZE);
2984 	if (msg == NULL) {
2985 		lprintf(LOG_ERR, "ipmitool: malloc failure");
2986 		return 1;
2987 	}
2988 	memset(msg, 0, IPMI_RAKP1_MESSAGE_SIZE);
2989 
2990 
2991 	msg[0] = 0; /* Message tag */
2992 
2993 	msg[1] = 0; /* reserved */
2994 	msg[2] = 0; /* reserved */
2995 	msg[3] = 0; /* reserved */
2996 
2997 	/* BMC session ID */
2998 	msg[4] = session->v2_data.bmc_id & 0xff;
2999 	msg[5] = (session->v2_data.bmc_id >> 8)  & 0xff;
3000 	msg[6] = (session->v2_data.bmc_id >> 16) & 0xff;
3001 	msg[7] = (session->v2_data.bmc_id >> 24) & 0xff;
3002 
3003 
3004 	/* We need a 16 byte random number */
3005 	if (lanplus_rand(session->v2_data.console_rand, 16))
3006 	{
3007 		// ERROR;
3008 		lprintf(LOG_ERR, "ERROR generating random number "
3009 			"in ipmi_lanplus_rakp1");
3010 		free(msg);
3011 		msg = NULL;
3012 		return 1;
3013 	}
3014 	memcpy(msg + 8, session->v2_data.console_rand, 16);
3015 	#if WORDS_BIGENDIAN
3016 	lanplus_swap(msg + 8, 16);
3017 	#endif
3018 
3019 	if (verbose > 1)
3020 		printbuf(session->v2_data.console_rand, 16,
3021 				 ">> Console generated random number");
3022 
3023 
3024 	/*
3025 	 * Requested maximum privilege level.
3026 	 */
3027 	msg[24] = intf->ssn_params.privlvl | intf->ssn_params.lookupbit;
3028 	session->v2_data.requested_role = msg[24];
3029 	msg[25] = 0; /* reserved */
3030 	msg[26] = 0; /* reserved */
3031 
3032 
3033 	/* Username specification */
3034 	msg[27] = strlen((const char *)intf->ssn_params.username);
3035 	if (msg[27] > IPMI_MAX_USER_NAME_LENGTH)
3036 	{
3037 		lprintf(LOG_ERR, "ERROR: user name too long.  "
3038 			"(Exceeds %d characters)",
3039 			IPMI_MAX_USER_NAME_LENGTH);
3040 		free(msg);
3041 		msg = NULL;
3042 		return 1;
3043 	}
3044 	memcpy(msg + 28, intf->ssn_params.username, msg[27]);
3045 
3046 	v2_payload.payload_type = IPMI_PAYLOAD_TYPE_RAKP_1;
3047 	if (ipmi_oem_active(intf, "i82571spt")) {
3048 		/*
3049 		 * The IPMI v2.0 spec hints on that all user name bytes
3050 		 * must be occupied (29:44).  The Intel 82571 GbE refuses
3051 		 * to establish a session if this field is shorter.
3052 		 */
3053 		v2_payload.payload_length = IPMI_RAKP1_MESSAGE_SIZE;
3054 	} else {
3055 		v2_payload.payload_length =
3056 			IPMI_RAKP1_MESSAGE_SIZE - (16 - msg[27]);
3057 	}
3058 	v2_payload.payload.rakp_1_message.message = msg;
3059 
3060 	rsp = ipmi_lanplus_send_payload(intf, &v2_payload);
3061 
3062 	free(msg);
3063 	msg = NULL;
3064 
3065 	if (rsp == NULL)
3066 	{
3067 		lprintf(LOG_WARNING, "> Error: no response from RAKP 1 message");
3068 		return 2;
3069 	}
3070 
3071 	session->v2_data.session_state = LANPLUS_STATE_RAKP_2_RECEIVED;
3072 
3073 	if (verbose)
3074 		lanplus_dump_rakp2_message(rsp, session->v2_data.auth_alg);
3075 
3076 
3077 
3078 	if (rsp->payload.rakp2_message.rakp_return_code != IPMI_RAKP_STATUS_NO_ERRORS)
3079 	{
3080 		lprintf(LOG_INFO, "RAKP 2 message indicates an error : %s",
3081 			val2str(rsp->payload.rakp2_message.rakp_return_code,
3082 				ipmi_rakp_return_codes));
3083 		rc = 1;
3084 	}
3085 
3086 	else
3087 	{
3088 		memcpy(session->v2_data.bmc_rand, rsp->payload.rakp2_message.bmc_rand, 16);
3089 		memcpy(session->v2_data.bmc_guid, rsp->payload.rakp2_message.bmc_guid, 16);
3090 
3091 		if (verbose > 2)
3092 			printbuf(session->v2_data.bmc_rand, 16, "bmc_rand");
3093 
3094 		/*
3095 		 * It is at this point that we have to decode the random number and determine
3096 		 * whether the BMC has authenticated.
3097 		 */
3098 		if (! lanplus_rakp2_hmac_matches(session,
3099 										 rsp->payload.rakp2_message.key_exchange_auth_code,
3100 										 intf))
3101 		{
3102 			/* Error */
3103 			lprintf(LOG_INFO, "> RAKP 2 HMAC is invalid");
3104 			session->v2_data.rakp2_return_code = IPMI_RAKP_STATUS_INVALID_INTEGRITY_CHECK_VALUE;
3105 								rc = 1;
3106 		}
3107 		else
3108 		{
3109 			/* Success */
3110 			session->v2_data.rakp2_return_code = IPMI_RAKP_STATUS_NO_ERRORS;
3111 		}
3112 	}
3113 
3114 	return rc;
3115 }
3116 
3117 
3118 
3119 /*
3120  * ipmi_lanplus_rakp3
3121  *
3122  * Build and send the RAKP 3 message as part of the IPMI v2 / RMCP+ session
3123  * negotiation protocol.  We also read and validate the RAKP 4 message received
3124  * from the BMC, here.  See section 13.20 of the IPMI v2 specification for
3125  * details.
3126  *
3127  * If the RAKP 2 return code is not IPMI_RAKP_STATUS_NO_ERRORS, we will
3128  * exit with an error code immediately after sendint the RAKP 3 message.
3129  *
3130  * param intf is the intf that holds all the state we are concerned with
3131  *
3132  * returns 0 on success
3133  *         1 on failure
3134  */
3135 static int
ipmi_lanplus_rakp3(struct ipmi_intf * intf)3136 ipmi_lanplus_rakp3(struct ipmi_intf * intf)
3137 {
3138 	struct ipmi_v2_payload v2_payload;
3139 	struct ipmi_session * session = intf->session;
3140 	uint8_t * msg;
3141 	struct ipmi_rs * rsp;
3142 
3143 	assert(session->v2_data.session_state == LANPLUS_STATE_RAKP_2_RECEIVED);
3144 
3145 	/*
3146 	 * Build a RAKP 3 message
3147 	 */
3148 	msg = (uint8_t*)malloc(IPMI_RAKP3_MESSAGE_MAX_SIZE);
3149 	if (msg == NULL) {
3150 		lprintf(LOG_ERR, "ipmitool: malloc failure");
3151 		return 1;
3152 	}
3153 	memset(msg, 0, IPMI_RAKP3_MESSAGE_MAX_SIZE);
3154 
3155 
3156 	msg[0] = 0; /* Message tag */
3157 	msg[1] = session->v2_data.rakp2_return_code;
3158 
3159 	msg[2] = 0; /* reserved */
3160 	msg[3] = 0; /* reserved */
3161 
3162 	/* BMC session ID */
3163 	msg[4] = session->v2_data.bmc_id & 0xff;
3164 	msg[5] = (session->v2_data.bmc_id >> 8)  & 0xff;
3165 	msg[6] = (session->v2_data.bmc_id >> 16) & 0xff;
3166 	msg[7] = (session->v2_data.bmc_id >> 24) & 0xff;
3167 
3168 	v2_payload.payload_type                   = IPMI_PAYLOAD_TYPE_RAKP_3;
3169 	v2_payload.payload_length                 = 8;
3170 	v2_payload.payload.rakp_3_message.message = msg;
3171 
3172 	/*
3173 	 * If the rakp2 return code indicates and error, we don't have to
3174 	 * generate an authcode or session integrity key.  In that case, we
3175 	 * are simply sending a RAKP 3 message to indicate to the BMC that the
3176 	 * RAKP 2 message caused an error.
3177 	 */
3178 	if (session->v2_data.rakp2_return_code == IPMI_RAKP_STATUS_NO_ERRORS)
3179 	{
3180 		uint32_t auth_length;
3181 
3182 		if (lanplus_generate_rakp3_authcode(msg + 8, session, &auth_length, intf))
3183 		{
3184 			/* Error */
3185 			lprintf(LOG_INFO, "> Error generating RAKP 3 authcode");
3186 			free(msg);
3187 			msg = NULL;
3188 			return 1;
3189 		}
3190 		else
3191 		{
3192 			/* Success */
3193 			v2_payload.payload_length += auth_length;
3194 		}
3195 
3196 		/* Generate our Session Integrity Key, K1, and K2 */
3197 		if (lanplus_generate_sik(session, intf))
3198 		{
3199 			/* Error */
3200 			lprintf(LOG_INFO, "> Error generating session integrity key");
3201 			free(msg);
3202 			msg = NULL;
3203 			return 1;
3204 		}
3205 		else if (lanplus_generate_k1(session))
3206 		{
3207 			/* Error */
3208 			lprintf(LOG_INFO, "> Error generating K1 key");
3209 			free(msg);
3210 			msg = NULL;
3211 			return 1;
3212 		}
3213 		else if (lanplus_generate_k2(session))
3214 		{
3215 			/* Error */
3216 			lprintf(LOG_INFO, "> Error generating K1 key");
3217 			free(msg);
3218 			msg = NULL;
3219 			return 1;
3220 		}
3221 	}
3222 
3223 
3224 	rsp = ipmi_lanplus_send_payload(intf, &v2_payload);
3225 
3226 	free(msg);
3227 	msg = NULL;
3228 
3229 	if (session->v2_data.rakp2_return_code != IPMI_RAKP_STATUS_NO_ERRORS)
3230 	{
3231 		/*
3232 		 * If the previous RAKP 2 message received was deemed erroneous,
3233 		 * we have nothing else to do here.  We only sent the RAKP 3 message
3234 		 * to indicate to the BMC that the RAKP 2 message failed.
3235 		 */
3236 		return 1;
3237 	}
3238 	else if (rsp == NULL)
3239 	{
3240 		lprintf(LOG_WARNING, "> Error: no response from RAKP 3 message");
3241 		return 2;
3242 	}
3243 
3244 
3245 	/*
3246 	 * We have a RAKP 4 message to chew on.
3247 	 */
3248 	if (verbose)
3249 		lanplus_dump_rakp4_message(rsp, session->v2_data.auth_alg);
3250 
3251 
3252 	if (rsp->payload.open_session_response.rakp_return_code != IPMI_RAKP_STATUS_NO_ERRORS)
3253 	{
3254 		lprintf(LOG_INFO, "RAKP 4 message indicates an error : %s",
3255 			val2str(rsp->payload.rakp4_message.rakp_return_code,
3256 				ipmi_rakp_return_codes));
3257 		return 1;
3258 	}
3259 
3260 	else
3261 	{
3262 		/* Validate the authcode */
3263 		if (lanplus_rakp4_hmac_matches(session,
3264 										rsp->payload.rakp4_message.integrity_check_value,
3265 										intf))
3266 		{
3267 			/* Success */
3268 			session->v2_data.session_state = LANPLUS_STATE_ACTIVE;
3269 		}
3270 		else
3271 		{
3272 			/* Error */
3273 			lprintf(LOG_INFO, "> RAKP 4 message has invalid integrity check value");
3274 			return 1;
3275 		}
3276 	}
3277 
3278 	intf->abort = 0;
3279 	return 0;
3280 }
3281 
3282 
3283 
3284 /**
3285  * ipmi_lan_close
3286  */
3287 void
ipmi_lanplus_close(struct ipmi_intf * intf)3288 ipmi_lanplus_close(struct ipmi_intf * intf)
3289 {
3290 	if (!intf->abort && intf->session)
3291 		ipmi_close_session_cmd(intf);
3292 
3293 	if (intf->fd >= 0) {
3294 		close(intf->fd);
3295 		intf->fd = -1;
3296 	}
3297 
3298 	ipmi_req_clear_entries();
3299 	ipmi_intf_session_cleanup(intf);
3300 	intf->opened = 0;
3301 	intf->manufacturer_id = IPMI_OEM_UNKNOWN;
3302 	intf = NULL;
3303 }
3304 
3305 
3306 
3307 static int
ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf)3308 ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf)
3309 {
3310 	struct ipmi_rs * rsp;
3311 	struct ipmi_rq req;
3312 	uint8_t backupBridgePossible;
3313 	uint8_t privlvl = intf->ssn_params.privlvl;
3314 
3315 	if (privlvl <= IPMI_SESSION_PRIV_USER)
3316 		return 0;	/* no need to set higher */
3317 
3318 	backupBridgePossible = bridgePossible;
3319 
3320 	bridgePossible = 0;
3321 
3322 	memset(&req, 0, sizeof(req));
3323 	req.msg.netfn		= IPMI_NETFN_APP;
3324 	req.msg.cmd		= 0x3b;
3325 	req.msg.data		= &privlvl;
3326 	req.msg.data_len	= 1;
3327 
3328 	rsp = intf->sendrecv(intf, &req);
3329 	if (rsp == NULL) {
3330 		lprintf(LOG_ERR, "Set Session Privilege Level to %s failed",
3331 			val2str(privlvl, ipmi_privlvl_vals));
3332 		bridgePossible = backupBridgePossible;
3333 		return -1;
3334 	}
3335 	if (verbose > 2)
3336 		printbuf(rsp->data, rsp->data_len, "set_session_privlvl");
3337 
3338 	if (rsp->ccode > 0) {
3339 		lprintf(LOG_ERR, "Set Session Privilege Level to %s failed: %s",
3340 			val2str(privlvl, ipmi_privlvl_vals),
3341 			val2str(rsp->ccode, completion_code_vals));
3342 		bridgePossible = backupBridgePossible;
3343 		return -1;
3344 	}
3345 
3346 	lprintf(LOG_DEBUG, "Set Session Privilege Level to %s\n",
3347 		val2str(rsp->data[0], ipmi_privlvl_vals));
3348 
3349 	bridgePossible = backupBridgePossible;
3350 
3351 	return 0;
3352 }
3353 
3354 /**
3355  * ipmi_lanplus_open
3356  */
3357 int
ipmi_lanplus_open(struct ipmi_intf * intf)3358 ipmi_lanplus_open(struct ipmi_intf * intf)
3359 {
3360 	int rc;
3361 	int retry;
3362 	struct get_channel_auth_cap_rsp auth_cap;
3363 	struct ipmi_session_params *params;
3364 	struct ipmi_session *session;
3365 
3366 	if (!intf)
3367 		return -1;
3368 
3369 	if (intf->opened)
3370 		return intf->fd;
3371 
3372 	params = &intf->ssn_params;
3373 
3374 	if (!params->port)
3375 		params->port = IPMI_LANPLUS_PORT;
3376 	if (!params->privlvl)
3377 		params->privlvl = IPMI_SESSION_PRIV_ADMIN;
3378 	if (!params->timeout)
3379 		params->timeout = IPMI_LAN_TIMEOUT;
3380 	if (!params->retry)
3381 		params->retry = IPMI_LAN_RETRY;
3382 
3383 	if (params->hostname == NULL || strlen((const char *)params->hostname) == 0) {
3384 		lprintf(LOG_ERR, "No hostname specified!");
3385 		return -1;
3386 	}
3387 
3388 	if (ipmi_intf_socket_connect(intf) == -1) {
3389 		lprintf(LOG_ERR, "Could not open socket!");
3390 		goto fail;
3391 	}
3392 
3393 	session = (struct ipmi_session *)malloc(sizeof (struct ipmi_session));
3394 	if (!session) {
3395 		lprintf(LOG_ERR, "ipmitool: malloc failure");
3396 		goto fail;
3397 	}
3398 
3399 	intf->session = session;
3400 
3401 	/* Setup our lanplus session state */
3402 	memset(session, 0, sizeof(struct ipmi_session));
3403 	session->timeout = params->timeout;
3404 	memcpy(&session->authcode, &params->authcode_set, sizeof(session->authcode));
3405 	session->v2_data.auth_alg         = IPMI_AUTH_RAKP_NONE;
3406 	session->v2_data.crypt_alg        = IPMI_CRYPT_NONE;
3407 	session->sol_data.sequence_number = 1;
3408 
3409 	intf->opened = 1;
3410 	intf->abort = 1;
3411 
3412 	/*
3413 	 *
3414 	 * Make sure the BMC supports IPMI v2 / RMCP+
3415 	 */
3416 	if (!ipmi_oem_active(intf, "i82571spt") &&
3417 			ipmi_get_auth_capabilities_cmd(intf, &auth_cap)) {
3418 		lprintf(LOG_INFO, "Error issuing Get Channel "
3419 			"Authentication Capabilies request");
3420 		goto fail;
3421 	}
3422 
3423 	if (!ipmi_oem_active(intf, "i82571spt") && ! auth_cap.v20_data_available) {
3424 		lprintf(LOG_INFO, "This BMC does not support IPMI v2 / RMCP+");
3425 		goto fail;
3426 	}
3427 
3428 	/*
3429 	 * If the open/rakp1/rakp3 sequence encounters a timeout, the whole sequence
3430 	 * needs to restart. The individual messages are not individually retryable,
3431 	 * as the session state is advancing.
3432 	 */
3433 	for (retry = 0; retry < IPMI_LAN_RETRY; retry++) {
3434 		session->v2_data.session_state = LANPLUS_STATE_PRESESSION;
3435 		/*
3436 		 * Open session
3437 		 */
3438 		if ((rc = ipmi_lanplus_open_session(intf)) == 1) {
3439 			goto fail;
3440 		}
3441 		if (rc == 2) {
3442 			lprintf(LOG_DEBUG, "Retry lanplus open session, %d", retry);
3443 			continue;
3444 		}
3445 		/*
3446 		 * RAKP 1
3447 		 */
3448 		if ((rc = ipmi_lanplus_rakp1(intf)) == 1) {
3449 			goto fail;
3450 		}
3451 		if (rc == 2) {
3452 			lprintf(LOG_DEBUG, "Retry lanplus rakp1, %d", retry);
3453 			continue;
3454 		}
3455 		/*
3456 		 * RAKP 3
3457 		 */
3458 		if ((rc = ipmi_lanplus_rakp3(intf)) == 1) {
3459 			goto fail;
3460 		}
3461 		if (rc == 0) break;
3462 		lprintf(LOG_DEBUG,"Retry lanplus rakp3, %d", retry);
3463 	}
3464 
3465 	lprintf(LOG_DEBUG, "IPMIv2 / RMCP+ SESSION OPENED SUCCESSFULLY\n");
3466 
3467 	intf->abort = 0;
3468 
3469 	if (!ipmi_oem_active(intf, "i82571spt")) {
3470 		rc = ipmi_set_session_privlvl_cmd(intf);
3471 		if (rc < 0) {
3472 			goto fail;
3473 		}
3474 	}
3475 	intf->manufacturer_id = ipmi_get_oem(intf);
3476 
3477 	/* automatically detect interface request and response sizes */
3478 	hpm2_detect_max_payload_size(intf);
3479 
3480 	bridgePossible = 1;
3481 	return intf->fd;
3482 
3483  fail:
3484 	lprintf(LOG_ERR, "Error: Unable to establish IPMI v2 / RMCP+ session");
3485 	intf->close(intf);
3486 	return -1;
3487 }
3488 
3489 
3490 
test_crypt1(void)3491 void test_crypt1(void)
3492 {
3493 	uint8_t key[]  =
3494 		{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
3495 		 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14};
3496 
3497 	uint16_t  bytes_encrypted;
3498 	uint16_t  bytes_decrypted;
3499 	uint8_t   decrypt_buffer[1000];
3500 	uint8_t   encrypt_buffer[1000];
3501 
3502 	uint8_t data[] =
3503 		{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
3504 		 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
3505 		 0x11, 0x12};
3506 
3507 	printbuf(data, sizeof(data), "original data");
3508 
3509 	if (lanplus_encrypt_payload(IPMI_CRYPT_AES_CBC_128,
3510 								key,
3511 								data,
3512 								sizeof(data),
3513 								encrypt_buffer,
3514 								&bytes_encrypted))
3515 	{
3516 		lprintf(LOG_ERR, "Encrypt test failed");
3517 		assert(0);
3518 	}
3519 	printbuf(encrypt_buffer, bytes_encrypted, "encrypted payload");
3520 
3521 
3522 	if (lanplus_decrypt_payload(IPMI_CRYPT_AES_CBC_128,
3523 								key,
3524 								encrypt_buffer,
3525 								bytes_encrypted,
3526 								decrypt_buffer,
3527 								&bytes_decrypted))
3528 	{
3529 		lprintf(LOG_ERR, "Decrypt test failed\n");
3530 		assert(0);
3531 	}
3532 	printbuf(decrypt_buffer, bytes_decrypted, "decrypted payload");
3533 
3534 	lprintf(LOG_DEBUG, "\nDone testing the encrypt/decyrpt methods!\n");
3535 	exit(0);
3536 }
3537 
3538 
3539 
test_crypt2(void)3540 void test_crypt2(void)
3541 {
3542 	uint8_t key[]  =
3543 		{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
3544 		 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14};
3545 	uint8_t iv[]  =
3546 		  {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
3547 			0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14};
3548 	uint8_t data[8] = "12345678";
3549 
3550 	uint8_t encrypt_buffer[1000];
3551 	uint8_t decrypt_buffer[1000];
3552 	uint32_t bytes_encrypted;
3553 	uint32_t bytes_decrypted;
3554 
3555 	printbuf((const uint8_t *)data, strlen((const char *)data), "input data");
3556 
3557 	lanplus_encrypt_aes_cbc_128(iv,
3558 								key,
3559 								data,
3560 								strlen((const char *)data),
3561 								encrypt_buffer,
3562 								&bytes_encrypted);
3563 	printbuf((const uint8_t *)encrypt_buffer, bytes_encrypted, "encrypt_buffer");
3564 
3565 	lanplus_decrypt_aes_cbc_128(iv,
3566 								key,
3567 								encrypt_buffer,
3568 								bytes_encrypted,
3569 								decrypt_buffer,
3570 								&bytes_decrypted);
3571 	printbuf((const uint8_t *)decrypt_buffer, bytes_decrypted, "decrypt_buffer");
3572 
3573 	lprintf(LOG_INFO, "\nDone testing the encrypt/decyrpt methods!\n");
3574 	exit(0);
3575 }
3576 
3577 
3578 /**
3579  * send a get device id command to keep session active
3580  */
3581 static int
ipmi_lanplus_keepalive(struct ipmi_intf * intf)3582 ipmi_lanplus_keepalive(struct ipmi_intf * intf)
3583 {
3584 	struct ipmi_rs * rsp;
3585 	struct ipmi_rq req = {
3586 		.msg = {
3587 			.netfn = IPMI_NETFN_APP,
3588 			.cmd = 1,
3589 		}
3590 	};
3591 
3592 	if (!intf->opened)
3593 		return 0;
3594 
3595 	rsp = intf->sendrecv(intf, &req);
3596 	while (rsp != NULL && is_sol_packet(rsp)) {
3597 					 /* rsp was SOL data instead of our answer */
3598 					 /* since it didn't go through the sol recv, do sol recv stuff here */
3599 					 ack_sol_packet(intf, rsp);
3600 					 check_sol_packet_for_new_data(intf, rsp);
3601 					 if (rsp->data_len)
3602 								intf->session->sol_data.sol_input_handler(rsp);
3603 		rsp = ipmi_lan_poll_recv(intf);
3604 		if (rsp == NULL) /* the get device id answer never got back, but retry mechanism was bypassed by SOL data */
3605 			return 0; /* so get device id command never returned, the connection is still alive */
3606 		  }
3607 
3608 	if (rsp == NULL)
3609 		return -1;
3610 	if (rsp->ccode > 0)
3611 		return -1;
3612 
3613 	return 0;
3614 }
3615 
3616 
3617 /**
3618  * ipmi_lanplus_setup
3619  */
ipmi_lanplus_setup(struct ipmi_intf * intf)3620 static int ipmi_lanplus_setup(struct ipmi_intf * intf)
3621 {
3622 	//test_crypt1();
3623 	assert("ipmi_lanplus_setup");
3624 
3625 	if (lanplus_seed_prng(16))
3626 		return -1;
3627 
3628     /* setup default LAN maximum request and response sizes */
3629     intf->max_request_data_size = IPMI_LAN_MAX_REQUEST_SIZE;
3630     intf->max_response_data_size = IPMI_LAN_MAX_RESPONSE_SIZE;
3631 
3632 	return 0;
3633 }
3634 
ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf,uint16_t size)3635 static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size)
3636 {
3637 	if (intf->ssn_params.cipher_suite_id == 3) {
3638 		/*
3639 		 * encrypted payload can only be multiple of 16 bytes
3640 		 */
3641 		size &= ~15;
3642 
3643 		/*
3644 		 * decrement payload size on confidentiality header size
3645 		 * plus minimal confidentiality trailer size
3646 		 */
3647 		size -= (16 + 1);
3648 	}
3649 
3650 	intf->max_request_data_size = size;
3651 }
3652 
ipmi_lanp_set_max_rp_data_size(struct ipmi_intf * intf,uint16_t size)3653 static void ipmi_lanp_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size)
3654 {
3655 	if (intf->ssn_params.cipher_suite_id == 3) {
3656 		/*
3657 		 * encrypted payload can only be multiple of 16 bytes
3658 		 */
3659 		size &= ~15;
3660 
3661 		/*
3662 		 * decrement payload size on confidentiality header size
3663 		 * plus minimal confidentiality trailer size
3664 		 */
3665 		size -= (16 + 1);
3666 	}
3667 
3668 	intf->max_response_data_size = size;
3669 }
3670