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