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