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