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