xref: /openbmc/ipmitool/src/plugins/lan/lan.c (revision 82f6175d)
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 <fcntl.h>
48 
49 #include <ipmitool/helper.h>
50 #include <ipmitool/log.h>
51 #include <ipmitool/bswap.h>
52 #include <ipmitool/ipmi.h>
53 #include <ipmitool/ipmi_sel.h>
54 #include <ipmitool/ipmi_intf.h>
55 #include <ipmitool/ipmi_oem.h>
56 #include <ipmitool/ipmi_strings.h>
57 #include <ipmitool/ipmi_constants.h>
58 #include <ipmitool/hpm2.h>
59 
60 #if HAVE_CONFIG_H
61 # include <config.h>
62 #endif
63 
64 #include "lan.h"
65 #include "rmcp.h"
66 #include "asf.h"
67 #include "auth.h"
68 
69 #define IPMI_LAN_TIMEOUT	2
70 #define IPMI_LAN_RETRY		4
71 #define IPMI_LAN_PORT		0x26f
72 #define IPMI_LAN_CHANNEL_E	0x0e
73 
74 /*
75  * LAN interface is required to support 45 byte request transactions and
76  * 42 byte response transactions.
77  */
78 #define IPMI_LAN_MAX_REQUEST_SIZE	38	/* 45 - 7 */
79 #define IPMI_LAN_MAX_RESPONSE_SIZE	34	/* 42 - 8 */
80 
81 extern const struct valstr ipmi_privlvl_vals[];
82 extern const struct valstr ipmi_authtype_session_vals[];
83 extern int verbose;
84 
85 struct ipmi_rq_entry * ipmi_req_entries;
86 static struct ipmi_rq_entry * ipmi_req_entries_tail;
87 static uint8_t bridge_possible = 0;
88 
89 static int ipmi_lan_send_packet(struct ipmi_intf * intf, uint8_t * data, int data_len);
90 static struct ipmi_rs * ipmi_lan_recv_packet(struct ipmi_intf * intf);
91 static struct ipmi_rs * ipmi_lan_poll_recv(struct ipmi_intf * intf);
92 static int ipmi_lan_setup(struct ipmi_intf * intf);
93 static int ipmi_lan_keepalive(struct ipmi_intf * intf);
94 static struct ipmi_rs * ipmi_lan_recv_sol(struct ipmi_intf * intf);
95 static struct ipmi_rs * ipmi_lan_send_sol(struct ipmi_intf * intf,
96 					  struct ipmi_v2_payload * payload);
97 static struct ipmi_rs * ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req);
98 static int ipmi_lan_send_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp);
99 static int ipmi_lan_open(struct ipmi_intf * intf);
100 static void ipmi_lan_close(struct ipmi_intf * intf);
101 static int ipmi_lan_ping(struct ipmi_intf * intf);
102 static void ipmi_lan_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size);
103 static void ipmi_lan_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size);
104 
105 struct ipmi_intf ipmi_lan_intf = {
106 	.name = "lan",
107 	.desc = "IPMI v1.5 LAN Interface",
108 	.setup = ipmi_lan_setup,
109 	.open = ipmi_lan_open,
110 	.close = ipmi_lan_close,
111 	.sendrecv = ipmi_lan_send_cmd,
112 	.sendrsp = ipmi_lan_send_rsp,
113 	.recv_sol = ipmi_lan_recv_sol,
114 	.send_sol = ipmi_lan_send_sol,
115 	.keepalive = ipmi_lan_keepalive,
116 	.set_max_request_data_size = ipmi_lan_set_max_rq_data_size,
117 	.set_max_response_data_size = ipmi_lan_set_max_rp_data_size,
118 	.target_addr = IPMI_BMC_SLAVE_ADDR,
119 };
120 
121 static struct ipmi_rq_entry *
122 ipmi_req_add_entry(struct ipmi_intf * intf, struct ipmi_rq * req, uint8_t req_seq)
123 {
124 	struct ipmi_rq_entry * e;
125 
126 	e = malloc(sizeof(struct ipmi_rq_entry));
127 	if (e == NULL) {
128 		lprintf(LOG_ERR, "ipmitool: malloc failure");
129 		return NULL;
130 	}
131 
132 	memset(e, 0, sizeof(struct ipmi_rq_entry));
133 	memcpy(&e->req, req, sizeof(struct ipmi_rq));
134 
135 	e->intf = intf;
136 	e->rq_seq = req_seq;
137 
138 	if (ipmi_req_entries == NULL)
139 		ipmi_req_entries = e;
140 	else
141 		ipmi_req_entries_tail->next = e;
142 
143 	ipmi_req_entries_tail = e;
144 	lprintf(LOG_DEBUG+3, "added list entry seq=0x%02x cmd=0x%02x",
145 		e->rq_seq, e->req.msg.cmd);
146 	return e;
147 }
148 
149 static struct ipmi_rq_entry *
150 ipmi_req_lookup_entry(uint8_t seq, uint8_t cmd)
151 {
152 	struct ipmi_rq_entry * e = ipmi_req_entries;
153 	while (e && (e->rq_seq != seq || e->req.msg.cmd != cmd)) {
154 		if (e->next == NULL || e == e->next)
155 			return NULL;
156 		e = e->next;
157 	}
158 	return e;
159 }
160 
161 static void
162 ipmi_req_remove_entry(uint8_t seq, uint8_t cmd)
163 {
164 	struct ipmi_rq_entry * p, * e, * saved_next_entry;
165 
166 	e = p = ipmi_req_entries;
167 
168 	while (e && (e->rq_seq != seq || e->req.msg.cmd != cmd)) {
169 		p = e;
170 		e = e->next;
171 	}
172 	if (e) {
173 		lprintf(LOG_DEBUG+3, "removed list entry seq=0x%02x cmd=0x%02x",
174 			seq, cmd);
175 		saved_next_entry = e->next;
176 		p->next = (p->next == e->next) ? NULL : e->next;
177 		/* If entry being removed is first in list, fix up list head */
178 		if (ipmi_req_entries == e) {
179 			if (ipmi_req_entries != p)
180 				ipmi_req_entries = p;
181 			else
182 				ipmi_req_entries = saved_next_entry;
183 		}
184 		/* If entry being removed is last in list, fix up list tail */
185 		if (ipmi_req_entries_tail == e) {
186 			if (ipmi_req_entries_tail != p)
187 				ipmi_req_entries_tail = p;
188 			else
189 				ipmi_req_entries_tail = NULL;
190 		}
191 		if (e->msg_data) {
192 			free(e->msg_data);
193 			e->msg_data = NULL;
194 		}
195 		free(e);
196 		e = NULL;
197 	}
198 }
199 
200 static void
201 ipmi_req_clear_entries(void)
202 {
203 	struct ipmi_rq_entry * p, * e;
204 
205 	e = ipmi_req_entries;
206 	while (e) {
207 		lprintf(LOG_DEBUG+3, "cleared list entry seq=0x%02x cmd=0x%02x",
208 			e->rq_seq, e->req.msg.cmd);
209 		if (e->next != NULL) {
210 			p = e->next;
211 			free(e);
212 			e = p;
213 		} else {
214 			free(e);
215 			e = NULL;
216 			break;
217 		}
218 	}
219 	ipmi_req_entries = NULL;
220 }
221 
222 static int
223 get_random(void *data, int len)
224 {
225 	int fd = open("/dev/urandom", O_RDONLY);
226 	int rv;
227 
228 	if (fd < 0)
229 		return errno;
230 	if (len < 0) {
231 		close(fd);
232 		return errno; /* XXX: ORLY? */
233 	}
234 
235 	rv = read(fd, data, len);
236 
237 	close(fd);
238 	return rv;
239 }
240 
241 static int
242 ipmi_lan_send_packet(struct ipmi_intf * intf, uint8_t * data, int data_len)
243 {
244 	if (verbose > 2)
245 		printbuf(data, data_len, "send_packet");
246 
247 	return send(intf->fd, data, data_len, 0);
248 }
249 
250 static struct ipmi_rs *
251 ipmi_lan_recv_packet(struct ipmi_intf * intf)
252 {
253 	static struct ipmi_rs rsp;
254 	fd_set read_set;
255 	fd_set err_set;
256 	struct timeval tmout;
257 	int ret;
258 
259 	FD_ZERO(&read_set);
260 	FD_SET(intf->fd, &read_set);
261 
262 	FD_ZERO(&err_set);
263 	FD_SET(intf->fd, &err_set);
264 
265 	tmout.tv_sec = intf->ssn_params.timeout;
266 	tmout.tv_usec = 0;
267 
268 	ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout);
269 	if (ret < 0 || FD_ISSET(intf->fd, &err_set) || !FD_ISSET(intf->fd, &read_set))
270 		return NULL;
271 
272 	/* the first read may return ECONNREFUSED because the rmcp ping
273 	 * packet--sent to UDP port 623--will be processed by both the
274 	 * BMC and the OS.
275 	 *
276 	 * The problem with this is that the ECONNREFUSED takes
277 	 * priority over any other received datagram; that means that
278 	 * the Connection Refused shows up _before_ the response packet,
279 	 * regardless of the order they were sent out.  (unless the
280 	 * response is read before the connection refused is returned)
281 	 */
282 	ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0);
283 
284 	if (ret < 0) {
285 		FD_ZERO(&read_set);
286 		FD_SET(intf->fd, &read_set);
287 
288 		FD_ZERO(&err_set);
289 		FD_SET(intf->fd, &err_set);
290 
291 		tmout.tv_sec = intf->ssn_params.timeout;
292 		tmout.tv_usec = 0;
293 
294 		ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout);
295 		if (ret < 0 || FD_ISSET(intf->fd, &err_set) || !FD_ISSET(intf->fd, &read_set))
296 			return NULL;
297 
298 		ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0);
299 		if (ret < 0)
300 			return NULL;
301 	}
302 
303 	if (ret == 0)
304 		return NULL;
305 
306 	rsp.data[ret] = '\0';
307 	rsp.data_len = ret;
308 
309 	if (verbose > 2)
310 		printbuf(rsp.data, rsp.data_len, "recv_packet");
311 
312 	return &rsp;
313 }
314 
315 /*
316  * parse response RMCP "pong" packet
317  *
318  * return -1 if ping response not received
319  * returns 0 if IPMI is NOT supported
320  * returns 1 if IPMI is supported
321  *
322  * udp.source	= 0x026f	// RMCP_UDP_PORT
323  * udp.dest	= ?		// udp.source from rmcp-ping
324  * udp.len	= ?
325  * udp.check	= ?
326  * rmcp.ver	= 0x06		// RMCP Version 1.0
327  * rmcp.__res	= 0x00		// RESERVED
328  * rmcp.seq	= 0xff		// no RMCP ACK
329  * rmcp.class	= 0x06		// RMCP_CLASS_ASF
330  * asf.iana	= 0x000011be	// ASF_RMCP_IANA
331  * asf.type	= 0x40		// ASF_TYPE_PONG
332  * asf.tag	= ?		// asf.tag from rmcp-ping
333  * asf.__res	= 0x00		// RESERVED
334  * asf.len	= 0x10		// 16 bytes
335  * asf.data[3:0]= 0x000011be	// IANA# = RMCP_ASF_IANA if no OEM
336  * asf.data[7:4]= 0x00000000	// OEM-defined (not for IPMI)
337  * asf.data[8]	= 0x81		// supported entities
338  * 				// [7]=IPMI [6:4]=RES [3:0]=ASF_1.0
339  * asf.data[9]	= 0x00		// supported interactions (reserved)
340  * asf.data[f:a]= 0x000000000000
341  */
342 static int
343 ipmi_handle_pong(struct ipmi_intf * intf, struct ipmi_rs * rsp)
344 {
345 	struct rmcp_pong * pong;
346 
347 	if (rsp == NULL)
348 		return -1;
349 
350 	pong = (struct rmcp_pong *)rsp->data;
351 
352 	lprintf(LOG_DEBUG,
353 		"Received IPMI/RMCP response packet: \n"
354 		"  IPMI%s Supported\n"
355 		"  ASF Version %s\n"
356 		"  RMCP Version %s\n"
357 		"  RMCP Sequence %d\n"
358 		"  IANA Enterprise %ld\n",
359 		(pong->sup_entities & 0x80) ? "" : " NOT",
360 		(pong->sup_entities & 0x01) ? "1.0" : "unknown",
361 		(pong->rmcp.ver == 6) ? "1.0" : "unknown",
362 		pong->rmcp.seq,
363 		ntohl(pong->iana));
364 
365 	return (pong->sup_entities & 0x80) ? 1 : 0;
366 }
367 
368 /* build and send RMCP presence ping packet
369  *
370  * RMCP ping
371  *
372  * udp.source	= ?
373  * udp.dest	= 0x026f	// RMCP_UDP_PORT
374  * udp.len	= ?
375  * udp.check	= ?
376  * rmcp.ver	= 0x06		// RMCP Version 1.0
377  * rmcp.__res	= 0x00		// RESERVED
378  * rmcp.seq	= 0xff		// no RMCP ACK
379  * rmcp.class	= 0x06		// RMCP_CLASS_ASF
380  * asf.iana	= 0x000011be	// ASF_RMCP_IANA
381  * asf.type	= 0x80		// ASF_TYPE_PING
382  * asf.tag	= ?		// ASF sequence number
383  * asf.__res	= 0x00		// RESERVED
384  * asf.len	= 0x00
385  *
386  */
387 static int
388 ipmi_lan_ping(struct ipmi_intf * intf)
389 {
390 	struct asf_hdr asf_ping = {
391 		.iana	= htonl(ASF_RMCP_IANA),
392 		.type	= ASF_TYPE_PING,
393 	};
394 	struct rmcp_hdr rmcp_ping = {
395 		.ver	= RMCP_VERSION_1,
396 		.class	= RMCP_CLASS_ASF,
397 		.seq	= 0xff,
398 	};
399 	uint8_t * data;
400 	int len = sizeof(rmcp_ping) + sizeof(asf_ping);
401 	int rv;
402 
403 	data = malloc(len);
404 	if (data == NULL) {
405 		lprintf(LOG_ERR, "ipmitool: malloc failure");
406 		return -1;
407 	}
408 	memset(data, 0, len);
409 	memcpy(data, &rmcp_ping, sizeof(rmcp_ping));
410 	memcpy(data+sizeof(rmcp_ping), &asf_ping, sizeof(asf_ping));
411 
412 	lprintf(LOG_DEBUG, "Sending IPMI/RMCP presence ping packet");
413 
414 	rv = ipmi_lan_send_packet(intf, data, len);
415 
416 	free(data);
417 	data = NULL;
418 
419 	if (rv < 0) {
420 		lprintf(LOG_ERR, "Unable to send IPMI presence ping packet");
421 		return -1;
422 	}
423 
424 	if (ipmi_lan_poll_recv(intf) == 0)
425 		return 0;
426 
427 	return 1;
428 }
429 
430 /*
431  * The "thump" functions are used to send an extra packet following each
432  * request message.  This may kick-start some BMCs that get confused with
433  * bad passwords or operate poorly under heavy network load.
434  */
435 static void
436 ipmi_lan_thump_first(struct ipmi_intf * intf)
437 {
438 	/* is this random data? */
439 	uint8_t data[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440 				   0x07, 0x20, 0x18, 0xc8, 0xc2, 0x01, 0x01, 0x3c };
441 	ipmi_lan_send_packet(intf, data, 16);
442 }
443 
444 static void
445 ipmi_lan_thump(struct ipmi_intf * intf)
446 {
447 	uint8_t data[10] = "thump";
448 	ipmi_lan_send_packet(intf, data, 10);
449 }
450 
451 static struct ipmi_rs *
452 ipmi_lan_poll_recv(struct ipmi_intf * intf)
453 {
454 	struct rmcp_hdr rmcp_rsp;
455 	struct ipmi_rs * rsp;
456 	struct ipmi_rq_entry * entry;
457 	int x=0, rv;
458 	uint8_t our_address = intf->my_addr;
459 
460 	if (our_address == 0)
461 		our_address = IPMI_BMC_SLAVE_ADDR;
462 
463 	rsp = ipmi_lan_recv_packet(intf);
464 
465 	while (rsp != NULL) {
466 
467 		/* parse response headers */
468 		memcpy(&rmcp_rsp, rsp->data, 4);
469 
470 		switch (rmcp_rsp.class) {
471 		case RMCP_CLASS_ASF:
472 			/* ping response packet */
473 			rv = ipmi_handle_pong(intf, rsp);
474 			return (rv <= 0) ? NULL : rsp;
475 		case RMCP_CLASS_IPMI:
476 			/* handled by rest of function */
477 			break;
478 		default:
479 			lprintf(LOG_DEBUG, "Invalid RMCP class: %x",
480 				rmcp_rsp.class);
481 			rsp = ipmi_lan_recv_packet(intf);
482 			continue;
483 		}
484 
485 		x = 4;
486 		rsp->session.authtype = rsp->data[x++];
487 		memcpy(&rsp->session.seq, rsp->data+x, 4);
488 		x += 4;
489 		memcpy(&rsp->session.id, rsp->data+x, 4);
490 		x += 4;
491 
492 		if (rsp->session.id == (intf->session->session_id + 0x10000000)) {
493 			/* With SOL, authtype is always NONE, so we have no authcode */
494 			rsp->session.payloadtype = IPMI_PAYLOAD_TYPE_SOL;
495 
496 			rsp->session.msglen = rsp->data[x++];
497 
498 			rsp->payload.sol_packet.packet_sequence_number =
499 				rsp->data[x++] & 0x0F;
500 
501 			rsp->payload.sol_packet.acked_packet_number =
502 				rsp->data[x++] & 0x0F;
503 
504 			rsp->payload.sol_packet.accepted_character_count =
505 				rsp->data[x++];
506 
507 			rsp->payload.sol_packet.is_nack =
508 				rsp->data[x] & 0x40;
509 
510 			rsp->payload.sol_packet.transfer_unavailable =
511 				rsp->data[x] & 0x20;
512 
513 			rsp->payload.sol_packet.sol_inactive =
514 				rsp->data[x] & 0x10;
515 
516 			rsp->payload.sol_packet.transmit_overrun =
517 				rsp->data[x] & 0x08;
518 
519 			rsp->payload.sol_packet.break_detected =
520 				rsp->data[x++] & 0x04;
521 
522 			x++; /* On ISOL there's and additional fifth byte before the data starts */
523 
524 			lprintf(LOG_DEBUG, "SOL sequence number     : 0x%02x",
525 				rsp->payload.sol_packet.packet_sequence_number);
526 
527 			lprintf(LOG_DEBUG, "SOL acked packet        : 0x%02x",
528 				rsp->payload.sol_packet.acked_packet_number);
529 
530 			lprintf(LOG_DEBUG, "SOL accepted char count : 0x%02x",
531 				rsp->payload.sol_packet.accepted_character_count);
532 
533 			lprintf(LOG_DEBUG, "SOL is nack             : %s",
534 				rsp->payload.sol_packet.is_nack? "true" : "false");
535 
536 			lprintf(LOG_DEBUG, "SOL xfer unavailable    : %s",
537 				rsp->payload.sol_packet.transfer_unavailable? "true" : "false");
538 
539 			lprintf(LOG_DEBUG, "SOL inactive            : %s",
540 				rsp->payload.sol_packet.sol_inactive? "true" : "false");
541 
542 			lprintf(LOG_DEBUG, "SOL transmit overrun    : %s",
543 				rsp->payload.sol_packet.transmit_overrun? "true" : "false");
544 
545 			lprintf(LOG_DEBUG, "SOL break detected      : %s",
546 				rsp->payload.sol_packet.break_detected? "true" : "false");
547 		}
548 		else
549 		{
550 			/* Standard IPMI 1.5 packet */
551 			rsp->session.payloadtype = IPMI_PAYLOAD_TYPE_IPMI;
552 			if (intf->session->active && (rsp->session.authtype || intf->session->authtype))
553 				x += 16;
554 
555 			rsp->session.msglen = rsp->data[x++];
556 			rsp->payload.ipmi_response.rq_addr = rsp->data[x++];
557 			rsp->payload.ipmi_response.netfn   = rsp->data[x] >> 2;
558 			rsp->payload.ipmi_response.rq_lun  = rsp->data[x++] & 0x3;
559 			x++;		/* checksum */
560 			rsp->payload.ipmi_response.rs_addr = rsp->data[x++];
561 			rsp->payload.ipmi_response.rq_seq  = rsp->data[x] >> 2;
562 			rsp->payload.ipmi_response.rs_lun  = rsp->data[x++] & 0x3;
563 			rsp->payload.ipmi_response.cmd     = rsp->data[x++];
564 			rsp->ccode          = rsp->data[x++];
565 
566 			if (verbose > 2)
567 				printbuf(rsp->data, rsp->data_len, "ipmi message header");
568 
569 			lprintf(LOG_DEBUG+1, "<< IPMI Response Session Header");
570 			lprintf(LOG_DEBUG+1, "<<   Authtype   : %s",
571 				val2str(rsp->session.authtype, ipmi_authtype_session_vals));
572 			lprintf(LOG_DEBUG+1, "<<   Sequence   : 0x%08lx",
573 				(long)rsp->session.seq);
574 			lprintf(LOG_DEBUG+1, "<<   Session ID : 0x%08lx",
575 				(long)rsp->session.id);
576 			lprintf(LOG_DEBUG+1, "<< IPMI Response Message Header");
577 			lprintf(LOG_DEBUG+1, "<<   Rq Addr    : %02x",
578 				rsp->payload.ipmi_response.rq_addr);
579 			lprintf(LOG_DEBUG+1, "<<   NetFn      : %02x",
580 				rsp->payload.ipmi_response.netfn);
581 			lprintf(LOG_DEBUG+1, "<<   Rq LUN     : %01x",
582 				rsp->payload.ipmi_response.rq_lun);
583 			lprintf(LOG_DEBUG+1, "<<   Rs Addr    : %02x",
584 				rsp->payload.ipmi_response.rs_addr);
585 			lprintf(LOG_DEBUG+1, "<<   Rq Seq     : %02x",
586 				rsp->payload.ipmi_response.rq_seq);
587 			lprintf(LOG_DEBUG+1, "<<   Rs Lun     : %01x",
588 				rsp->payload.ipmi_response.rs_lun);
589 			lprintf(LOG_DEBUG+1, "<<   Command    : %02x",
590 				rsp->payload.ipmi_response.cmd);
591 			lprintf(LOG_DEBUG+1, "<<   Compl Code : 0x%02x",
592 				rsp->ccode);
593 
594 			/* now see if we have outstanding entry in request list */
595 			entry = ipmi_req_lookup_entry(rsp->payload.ipmi_response.rq_seq,
596 						      rsp->payload.ipmi_response.cmd);
597 			if (entry) {
598 				lprintf(LOG_DEBUG+2, "IPMI Request Match found");
599 				if ((intf->target_addr != our_address) && bridge_possible) {
600 					if ((rsp->data_len) && (rsp->payload.ipmi_response.netfn == 7) &&
601 					    (rsp->payload.ipmi_response.cmd != 0x34)) {
602 						if (verbose > 2)
603 							printbuf(&rsp->data[x], rsp->data_len-x,
604 								 "bridge command response");
605 					}
606 					/* bridged command: lose extra header */
607 					if (entry->bridging_level &&
608 					    rsp->payload.ipmi_response.netfn == 7 &&
609 					    rsp->payload.ipmi_response.cmd == 0x34) {
610 						entry->bridging_level--;
611 						if (rsp->data_len - x - 1 == 0) {
612 							rsp = !rsp->ccode ? ipmi_lan_recv_packet(intf) : NULL;
613 							if (!entry->bridging_level)
614 								entry->req.msg.cmd = entry->req.msg.target_cmd;
615 							if (rsp == NULL) {
616 								ipmi_req_remove_entry(entry->rq_seq, entry->req.msg.cmd);
617 							}
618 							continue;
619 						} else {
620 							/* The bridged answer data are inside the incoming packet */
621 							memmove(rsp->data + x - 7,
622 								rsp->data + x,
623 								rsp->data_len - x - 1);
624 							rsp->data[x - 8] -= 8;
625 							rsp->data_len -= 8;
626 							entry->rq_seq = rsp->data[x - 3] >> 2;
627 							if (!entry->bridging_level)
628 								entry->req.msg.cmd = entry->req.msg.target_cmd;
629 							continue;
630 						}
631 					} else {
632 						//x += sizeof(rsp->payload.ipmi_response);
633 						if (rsp->data[x-1] != 0)
634 							lprintf(LOG_DEBUG, "WARNING: Bridged "
635 								"cmd ccode = 0x%02x",
636 								rsp->data[x-1]);
637 					}
638 				}
639 				ipmi_req_remove_entry(rsp->payload.ipmi_response.rq_seq,
640 						      rsp->payload.ipmi_response.cmd);
641 			} else {
642 				lprintf(LOG_INFO, "IPMI Request Match NOT FOUND");
643 				rsp = ipmi_lan_recv_packet(intf);
644 				continue;
645 			}
646 		}
647 
648 		break;
649 	}
650 
651 	/* shift response data to start of array */
652 	if (rsp && rsp->data_len > x) {
653 		rsp->data_len -= x;
654 		if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_IPMI)
655 			rsp->data_len -= 1; /* We don't want the checksum */
656 		memmove(rsp->data, rsp->data + x, rsp->data_len);
657 		memset(rsp->data + rsp->data_len, 0, IPMI_BUF_SIZE - rsp->data_len);
658 	}
659 
660 	return rsp;
661 }
662 
663 /*
664  * IPMI LAN Request Message Format
665  * +--------------------+
666  * |  rmcp.ver          | 4 bytes
667  * |  rmcp.__reserved   |
668  * |  rmcp.seq          |
669  * |  rmcp.class        |
670  * +--------------------+
671  * |  session.authtype  | 9 bytes
672  * |  session.seq       |
673  * |  session.id        |
674  * +--------------------+
675  * | [session.authcode] | 16 bytes (AUTHTYPE != none)
676  * +--------------------+
677  * |  message length    | 1 byte
678  * +--------------------+
679  * |  message.rs_addr   | 6 bytes
680  * |  message.netfn_lun |
681  * |  message.checksum  |
682  * |  message.rq_addr   |
683  * |  message.rq_seq    |
684  * |  message.cmd       |
685  * +--------------------+
686  * | [request data]     | data_len bytes
687  * +--------------------+
688  * |  checksum          | 1 byte
689  * +--------------------+
690  */
691 static struct ipmi_rq_entry *
692 ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req, int isRetry)
693 {
694 	struct rmcp_hdr rmcp = {
695 		.ver		= RMCP_VERSION_1,
696 		.class		= RMCP_CLASS_IPMI,
697 		.seq		= 0xff,
698 	};
699 	uint8_t * msg, * temp;
700 	int cs, mp, tmp;
701 	int ap = 0;
702 	int len = 0;
703 	int cs2 = 0, cs3 = 0;
704 	struct ipmi_rq_entry * entry;
705 	struct ipmi_session * s = intf->session;
706 	static int curr_seq = 0;
707 	uint8_t our_address = intf->my_addr;
708 
709 	if (our_address == 0)
710 		our_address = IPMI_BMC_SLAVE_ADDR;
711 
712 	if (isRetry == 0)
713 		curr_seq++;
714 
715 	if (curr_seq >= 64)
716 		curr_seq = 0;
717 
718 	// Bug in the existing code where it keeps on adding same command/seq pair
719 	// in the lookup entry list.
720 	// Check if we have cmd,seq pair already in our list. As we are not changing
721 	// the seq number we have to re-use the node which has existing
722 	// command and sequence number. If we add then we will have redundant node with
723 	// same cmd,seq pair
724 	entry = ipmi_req_lookup_entry(curr_seq, req->msg.cmd);
725 	if (entry)
726 	{
727 		// This indicates that we have already same command and seq in list
728 		// No need to add once again and we will re-use the existing node.
729 		// Only thing we have to do is clear the msg_data as we create
730 		// a new one below in the code for it.
731 		if (entry->msg_data) {
732 			free(entry->msg_data);
733 			entry->msg_data = NULL;
734 		}
735 	}
736 	else
737 	{
738 		// We dont have this request in the list so we can add it
739 		// to the list
740 		entry = ipmi_req_add_entry(intf, req, curr_seq);
741 		if (entry == NULL)
742 			return NULL;
743 	}
744 
745 	len = req->msg.data_len + 29;
746 	if (s->active && s->authtype)
747 		len += 16;
748 	if (intf->transit_addr != intf->my_addr && intf->transit_addr != 0)
749 		len += 8;
750 	msg = malloc(len);
751 	if (msg == NULL) {
752 		lprintf(LOG_ERR, "ipmitool: malloc failure");
753 		return NULL;
754 	}
755 	memset(msg, 0, len);
756 
757 	/* rmcp header */
758 	memcpy(msg, &rmcp, sizeof(rmcp));
759 	len = sizeof(rmcp);
760 
761 	/* ipmi session header */
762 	msg[len++] = s->active ? s->authtype : 0;
763 
764 	msg[len++] = s->in_seq & 0xff;
765 	msg[len++] = (s->in_seq >> 8) & 0xff;
766 	msg[len++] = (s->in_seq >> 16) & 0xff;
767 	msg[len++] = (s->in_seq >> 24) & 0xff;
768 	memcpy(msg+len, &s->session_id, 4);
769 	len += 4;
770 
771 	/* ipmi session authcode */
772 	if (s->active && s->authtype) {
773 		ap = len;
774 		memcpy(msg+len, s->authcode, 16);
775 		len += 16;
776 	}
777 
778 	/* message length */
779 	if ((intf->target_addr == our_address) || !bridge_possible) {
780 		entry->bridging_level = 0;
781 		msg[len++] = req->msg.data_len + 7;
782 		cs = mp = len;
783 	} else {
784 		/* bridged request: encapsulate w/in Send Message */
785 		entry->bridging_level = 1;
786 		msg[len++] = req->msg.data_len + 15 +
787 		  (intf->transit_addr != intf->my_addr && intf->transit_addr != 0 ? 8 : 0);
788 		cs = mp = len;
789 		msg[len++] = IPMI_BMC_SLAVE_ADDR;
790 		msg[len++] = IPMI_NETFN_APP << 2;
791 		tmp = len - cs;
792 		msg[len++] = ipmi_csum(msg+cs, tmp);
793 		cs2 = len;
794 		msg[len++] = IPMI_REMOTE_SWID;
795 		msg[len++] = curr_seq << 2;
796 		msg[len++] = 0x34;			/* Send Message rqst */
797 		entry->req.msg.target_cmd = entry->req.msg.cmd;	/* Save target command */
798 		entry->req.msg.cmd = 0x34;		/* (fixup request entry) */
799 
800 		if (intf->transit_addr == intf->my_addr || intf->transit_addr == 0) {
801 		        msg[len++] = (0x40|intf->target_channel); /* Track request*/
802 		} else {
803 		        entry->bridging_level++;
804                		msg[len++] = (0x40|intf->transit_channel); /* Track request*/
805 			cs = len;
806 			msg[len++] = intf->transit_addr;
807 			msg[len++] = IPMI_NETFN_APP << 2;
808 			tmp = len - cs;
809 			msg[len++] = ipmi_csum(msg+cs, tmp);
810 			cs3 = len;
811 			msg[len++] = intf->my_addr;
812 			msg[len++] = curr_seq << 2;
813 			msg[len++] = 0x34;			/* Send Message rqst */
814 			msg[len++] = (0x40|intf->target_channel); /* Track request */
815 		}
816 		cs = len;
817 	}
818 
819 	/* ipmi message header */
820 	msg[len++] = intf->target_addr;
821 	msg[len++] = req->msg.netfn << 2 | (req->msg.lun & 3);
822 	tmp = len - cs;
823 	msg[len++] = ipmi_csum(msg+cs, tmp);
824 	cs = len;
825 
826 	if (!entry->bridging_level)
827 		msg[len++] = IPMI_REMOTE_SWID;
828    /* Bridged message */
829 	else if (entry->bridging_level)
830 		msg[len++] = intf->my_addr;
831 
832 	entry->rq_seq = curr_seq;
833 	msg[len++] = entry->rq_seq << 2;
834 	msg[len++] = req->msg.cmd;
835 
836 	lprintf(LOG_DEBUG+1, ">> IPMI Request Session Header (level %d)", entry->bridging_level);
837 	lprintf(LOG_DEBUG+1, ">>   Authtype   : %s",
838 	       val2str(s->authtype, ipmi_authtype_session_vals));
839 	lprintf(LOG_DEBUG+1, ">>   Sequence   : 0x%08lx", (long)s->in_seq);
840 	lprintf(LOG_DEBUG+1, ">>   Session ID : 0x%08lx", (long)s->session_id);
841 	lprintf(LOG_DEBUG+1, ">> IPMI Request Message Header");
842 	lprintf(LOG_DEBUG+1, ">>   Rs Addr    : %02x", intf->target_addr);
843 	lprintf(LOG_DEBUG+1, ">>   NetFn      : %02x", req->msg.netfn);
844 	lprintf(LOG_DEBUG+1, ">>   Rs LUN     : %01x", 0);
845 	lprintf(LOG_DEBUG+1, ">>   Rq Addr    : %02x", IPMI_REMOTE_SWID);
846 	lprintf(LOG_DEBUG+1, ">>   Rq Seq     : %02x", entry->rq_seq);
847 	lprintf(LOG_DEBUG+1, ">>   Rq Lun     : %01x", 0);
848 	lprintf(LOG_DEBUG+1, ">>   Command    : %02x", req->msg.cmd);
849 
850 	/* message data */
851 	if (req->msg.data_len) {
852  		memcpy(msg+len, req->msg.data, req->msg.data_len);
853 		len += req->msg.data_len;
854 	}
855 
856 	/* second checksum */
857 	tmp = len - cs;
858 	msg[len++] = ipmi_csum(msg+cs, tmp);
859 
860 	/* bridged request: 2nd checksum */
861 	if (entry->bridging_level) {
862 		if (intf->transit_addr != intf->my_addr && intf->transit_addr != 0) {
863 			tmp = len - cs3;
864 			msg[len++] = ipmi_csum(msg+cs3, tmp);
865 		}
866 		tmp = len - cs2;
867 		msg[len++] = ipmi_csum(msg+cs2, tmp);
868 	}
869 
870 	if (s->active) {
871 		/*
872 		 * s->authcode is already copied to msg+ap but some
873 		 * authtypes require portions of the ipmi message to
874 		 * create the authcode so they must be done last.
875 		 */
876 		switch (s->authtype) {
877 		case IPMI_SESSION_AUTHTYPE_MD5:
878 			temp = ipmi_auth_md5(s, msg+mp, msg[mp-1]);
879 			memcpy(msg+ap, temp, 16);
880 			break;
881 		case IPMI_SESSION_AUTHTYPE_MD2:
882 			temp = ipmi_auth_md2(s, msg+mp, msg[mp-1]);
883 			memcpy(msg+ap, temp, 16);
884 			break;
885 		}
886 	}
887 
888 	if (s->in_seq) {
889 		s->in_seq++;
890 		if (s->in_seq == 0)
891 			s->in_seq++;
892 	}
893 
894 	entry->msg_len = len;
895 	entry->msg_data = msg;
896 
897 	return entry;
898 }
899 
900 static struct ipmi_rs *
901 ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
902 {
903 	struct ipmi_rq_entry * entry;
904 	struct ipmi_rs * rsp = NULL;
905 	int try = 0;
906 	int isRetry = 0;
907 
908 	lprintf(LOG_DEBUG, "ipmi_lan_send_cmd:opened=[%d], open=[%d]",
909 		intf->opened, intf->open);
910 
911 	if (intf->opened == 0 && intf->open != NULL) {
912 		if (intf->open(intf) < 0) {
913 			lprintf(LOG_DEBUG, "Failed to open LAN interface");
914 			return NULL;
915 		}
916 		lprintf(LOG_DEBUG, "\topened=[%d], open=[%d]",
917 			intf->opened, intf->open);
918 	}
919 
920 	for (;;) {
921 		isRetry = ( try > 0 ) ? 1 : 0;
922 
923 		entry = ipmi_lan_build_cmd(intf, req, isRetry);
924 		if (entry == NULL) {
925 			lprintf(LOG_ERR, "Aborting send command, unable to build");
926 			return NULL;
927 		}
928 
929 		if (ipmi_lan_send_packet(intf, entry->msg_data, entry->msg_len) < 0) {
930 			try++;
931 			usleep(5000);
932 			ipmi_req_remove_entry(entry->rq_seq, entry->req.msg.target_cmd);
933 			continue;
934 		}
935 
936 		/* if we are set to noanswer we do not expect response */
937 		if (intf->noanswer)
938 			break;
939 
940 		if (ipmi_oem_active(intf, "intelwv2"))
941 			ipmi_lan_thump(intf);
942 
943 		usleep(100);
944 
945 		rsp = ipmi_lan_poll_recv(intf);
946 
947 		/* Duplicate Request ccode most likely indicates a response to
948 		   a previous retry. Ignore and keep polling. */
949 		if((rsp != NULL) && (rsp->ccode == 0xcf)) {
950 			rsp = NULL;
951 			rsp = ipmi_lan_poll_recv(intf);
952 		}
953 
954 		if (rsp)
955 			break;
956 
957 		usleep(5000);
958 		if (++try >= intf->ssn_params.retry) {
959 			lprintf(LOG_DEBUG, "  No response from remote controller");
960 			break;
961 		}
962 	}
963 
964 	// We need to cleanup the existing entries from the list. Because if we
965 	// keep it and then when we send the new command and if the response is for
966 	// old command it still matches it and then returns success.
967 	// This is the corner case where the remote controller responds very slowly.
968 	//
969 	// Example: We have to send command 23 and 2d.
970 	// If we send command,seq as 23,10 and if we dont get any response it will
971 	// retry 4 times with 23,10 and then come out here and indicate that there is no
972 	// reponse from the remote controller and will send the next command for
973 	// ie 2d,11. And if the BMC is slow to respond and returns 23,10 then it
974 	// will match it in the list and will take response of command 23 as response
975 	// for command 2d and return success. So ideally when retries are done and
976 	// are out of this function we should be clearing the list to be safe so that
977 	// we dont match the old response with new request.
978 	//          [23, 10] --> BMC
979 	//          [23, 10] --> BMC
980 	//          [23, 10] --> BMC
981 	//          [23, 10] --> BMC
982 	//          [2D, 11] --> BMC
983 	//                   <-- [23, 10]
984 	//  here if we maintain 23,10 in the list then it will get matched and consider
985 	//  23 response as response for 2D.
986 	ipmi_req_clear_entries();
987 
988 	return rsp;
989 }
990 
991 static uint8_t *
992 ipmi_lan_build_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp, int * llen)
993 {
994 	struct rmcp_hdr rmcp = {
995 		.ver	= RMCP_VERSION_1,
996 		.class	= RMCP_CLASS_IPMI,
997 		.seq	= 0xff,
998 	};
999 	struct ipmi_session * s = intf->session;
1000 	int cs, mp, ap = 0, tmp;
1001 	int len;
1002 	uint8_t * msg;
1003 
1004 	len = rsp->data_len + 22;
1005 	if (s->active)
1006 		len += 16;
1007 
1008 	msg = malloc(len);
1009 	if (msg == NULL) {
1010 		lprintf(LOG_ERR, "ipmitool: malloc failure");
1011 		return NULL;
1012 	}
1013 	memset(msg, 0, len);
1014 
1015 	/* rmcp header */
1016 	memcpy(msg, &rmcp, 4);
1017 	len = sizeof(rmcp);
1018 
1019 	/* ipmi session header */
1020 	msg[len++] = s->active ? s->authtype : 0;
1021 
1022 	if (s->in_seq) {
1023 		s->in_seq++;
1024 		if (s->in_seq == 0)
1025 			s->in_seq++;
1026 	}
1027 	memcpy(msg+len, &s->in_seq, 4);
1028 	len += 4;
1029 	memcpy(msg+len, &s->session_id, 4);
1030 	len += 4;
1031 
1032 	/* session authcode, if session active and authtype is not none */
1033 	if (s->active && s->authtype) {
1034 		ap = len;
1035 		memcpy(msg+len, s->authcode, 16);
1036 		len += 16;
1037 	}
1038 
1039 	/* message length */
1040 	msg[len++] = rsp->data_len + 8;
1041 
1042 	/* message header */
1043 	cs = mp = len;
1044 	msg[len++] = IPMI_REMOTE_SWID;
1045 	msg[len++] = rsp->msg.netfn << 2;
1046 	tmp = len - cs;
1047 	msg[len++] = ipmi_csum(msg+cs, tmp);
1048 	cs = len;
1049 	msg[len++] = IPMI_BMC_SLAVE_ADDR;
1050 	msg[len++] = (rsp->msg.seq << 2) | (rsp->msg.lun & 3);
1051 	msg[len++] = rsp->msg.cmd;
1052 
1053 	/* completion code */
1054 	msg[len++] = rsp->ccode;
1055 
1056 	/* message data */
1057 	if (rsp->data_len) {
1058 		memcpy(msg+len, rsp->data, rsp->data_len);
1059 		len += rsp->data_len;
1060 	}
1061 
1062 	/* second checksum */
1063 	tmp = len - cs;
1064 	msg[len++] = ipmi_csum(msg+cs, tmp);
1065 
1066 	if (s->active) {
1067 		uint8_t * d;
1068 		switch (s->authtype) {
1069 		case IPMI_SESSION_AUTHTYPE_MD5:
1070 			d = ipmi_auth_md5(s, msg+mp, msg[mp-1]);
1071 			memcpy(msg+ap, d, 16);
1072 			break;
1073 		case IPMI_SESSION_AUTHTYPE_MD2:
1074 			d = ipmi_auth_md2(s, msg+mp, msg[mp-1]);
1075 			memcpy(msg+ap, d, 16);
1076 			break;
1077 		}
1078 	}
1079 
1080 	*llen = len;
1081 	return msg;
1082 }
1083 
1084 static int
1085 ipmi_lan_send_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp)
1086 {
1087 	uint8_t * msg;
1088 	int len = 0;
1089 	int rv;
1090 
1091 	msg = ipmi_lan_build_rsp(intf, rsp, &len);
1092 	if (len <= 0 || msg == NULL) {
1093 		lprintf(LOG_ERR, "Invalid response packet");
1094 		if (msg != NULL) {
1095 			free(msg);
1096 			msg = NULL;
1097 		}
1098 		return -1;
1099 	}
1100 
1101 	rv = sendto(intf->fd, msg, len, 0,
1102 		    (struct sockaddr *)&intf->session->addr,
1103 		    intf->session->addrlen);
1104 	if (rv < 0) {
1105 		lprintf(LOG_ERR, "Packet send failed");
1106 		if (msg != NULL) {
1107 			free(msg);
1108 			msg = NULL;
1109 		}
1110 		return -1;
1111 	}
1112 
1113 	if (msg != NULL) {
1114 		free(msg);
1115 		msg = NULL;
1116 	}
1117 	return 0;
1118 }
1119 
1120 /*
1121  * IPMI SOL Payload Format
1122  * +--------------------+
1123  * |  rmcp.ver          | 4 bytes
1124  * |  rmcp.__reserved   |
1125  * |  rmcp.seq          |
1126  * |  rmcp.class        |
1127  * +--------------------+
1128  * |  session.authtype  | 9 bytes
1129  * |  session.seq       |
1130  * |  session.id        |
1131  * +--------------------+
1132  * |  message length    | 1 byte
1133  * +--------------------+
1134  * |  sol.seq           | 5 bytes
1135  * |  sol.ack_seq       |
1136  * |  sol.acc_count     |
1137  * |  sol.control       |
1138  * |  sol.__reserved    |
1139  * +--------------------+
1140  * | [request data]     | data_len bytes
1141  * +--------------------+
1142  */
1143 uint8_t * ipmi_lan_build_sol_msg(struct ipmi_intf * intf,
1144 				 struct ipmi_v2_payload * payload,
1145 				 int * llen)
1146 {
1147 	struct rmcp_hdr rmcp = {
1148 		.ver		= RMCP_VERSION_1,
1149 		.class		= RMCP_CLASS_IPMI,
1150 		.seq		= 0xff,
1151 	};
1152 	struct ipmi_session * session = intf->session;
1153 
1154 	/* msg will hold the entire message to be sent */
1155 	uint8_t * msg;
1156 
1157 	int len = 0;
1158 
1159 	len =	sizeof(rmcp)                                 +  // RMCP Header (4)
1160 		10                                           +  // IPMI Session Header
1161 		5                                            +  // SOL header
1162 		payload->payload.sol_packet.character_count;    // The actual payload
1163 
1164 	msg = malloc(len);
1165 	if (msg == NULL) {
1166 		lprintf(LOG_ERR, "ipmitool: malloc failure");
1167 		return NULL;
1168 	}
1169 	memset(msg, 0, len);
1170 
1171 	/* rmcp header */
1172 	memcpy(msg, &rmcp, sizeof(rmcp));
1173 	len = sizeof(rmcp);
1174 
1175 	/* ipmi session header */
1176 	msg[len++] = 0; /* SOL is always authtype = NONE */
1177 	msg[len++] = session->in_seq & 0xff;
1178 	msg[len++] = (session->in_seq >> 8) & 0xff;
1179 	msg[len++] = (session->in_seq >> 16) & 0xff;
1180 	msg[len++] = (session->in_seq >> 24) & 0xff;
1181 
1182 	msg[len++] = session->session_id & 0xff;
1183 	msg[len++] = (session->session_id >> 8) & 0xff;
1184 	msg[len++] = (session->session_id >> 16) & 0xff;
1185 	msg[len++] = ((session->session_id >> 24) + 0x10) & 0xff; /* Add 0x10 to MSB for SOL */
1186 
1187 	msg[len++] = payload->payload.sol_packet.character_count + 5;
1188 
1189 	/* sol header */
1190 	msg[len++] = payload->payload.sol_packet.packet_sequence_number;
1191 	msg[len++] = payload->payload.sol_packet.acked_packet_number;
1192 	msg[len++] = payload->payload.sol_packet.accepted_character_count;
1193 	msg[len]    = payload->payload.sol_packet.is_nack           ? 0x40 : 0;
1194 	msg[len]   |= payload->payload.sol_packet.assert_ring_wor   ? 0x20 : 0;
1195 	msg[len]   |= payload->payload.sol_packet.generate_break    ? 0x10 : 0;
1196 	msg[len]   |= payload->payload.sol_packet.deassert_cts      ? 0x08 : 0;
1197 	msg[len]   |= payload->payload.sol_packet.deassert_dcd_dsr  ? 0x04 : 0;
1198 	msg[len]   |= payload->payload.sol_packet.flush_inbound     ? 0x02 : 0;
1199 	msg[len++] |= payload->payload.sol_packet.flush_outbound    ? 0x01 : 0;
1200 
1201 	len++; /* On SOL there's and additional fifth byte before the data starts */
1202 
1203 	if (payload->payload.sol_packet.character_count) {
1204 		/* We may have data to add */
1205 		memcpy(msg + len,
1206 		       payload->payload.sol_packet.data,
1207 		       payload->payload.sol_packet.character_count);
1208 		len += payload->payload.sol_packet.character_count;
1209 	}
1210 
1211 	session->in_seq++;
1212 	if (session->in_seq == 0)
1213 		session->in_seq++;
1214 
1215 	*llen = len;
1216 	return msg;
1217 }
1218 
1219 /*
1220  * is_sol_packet
1221  */
1222 static int
1223 is_sol_packet(struct ipmi_rs * rsp)
1224 {
1225 	return (rsp                                                           &&
1226 		(rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL));
1227 }
1228 
1229 
1230 
1231 /*
1232  * sol_response_acks_packet
1233  */
1234 static int
1235 sol_response_acks_packet(struct ipmi_rs         * rsp,
1236 			 struct ipmi_v2_payload * payload)
1237 {
1238 	return (is_sol_packet(rsp)                                            &&
1239 		payload                                                       &&
1240 		(payload->payload_type    == IPMI_PAYLOAD_TYPE_SOL)           &&
1241 		(rsp->payload.sol_packet.acked_packet_number ==
1242 		 payload->payload.sol_packet.packet_sequence_number));
1243 }
1244 
1245 /*
1246  * ipmi_lan_send_sol_payload
1247  *
1248  */
1249 static struct ipmi_rs *
1250 ipmi_lan_send_sol_payload(struct ipmi_intf * intf,
1251 			  struct ipmi_v2_payload * payload)
1252 {
1253 	struct ipmi_rs      * rsp = NULL;
1254 	uint8_t             * msg;
1255 	int                   len;
1256 	int                   try = 0;
1257 
1258 	if (intf->opened == 0 && intf->open != NULL) {
1259 		if (intf->open(intf) < 0)
1260 			return NULL;
1261 	}
1262 
1263 	msg = ipmi_lan_build_sol_msg(intf, payload, &len);
1264 	if (len <= 0 || msg == NULL) {
1265 		lprintf(LOG_ERR, "Invalid SOL payload packet");
1266 		if (msg != NULL) {
1267 			free(msg);
1268 			msg = NULL;
1269 		}
1270 		return NULL;
1271 	}
1272 
1273 	lprintf(LOG_DEBUG, ">> SENDING A SOL MESSAGE\n");
1274 
1275 	for (;;) {
1276 		if (ipmi_lan_send_packet(intf, msg, len) < 0) {
1277 			try++;
1278 			usleep(5000);
1279 			continue;
1280 		}
1281 
1282 		/* if we are set to noanswer we do not expect response */
1283 		if (intf->noanswer)
1284 			break;
1285 
1286 		if (payload->payload.sol_packet.packet_sequence_number == 0) {
1287 			/* We're just sending an ACK.  No need to retry. */
1288 			break;
1289 		}
1290 
1291 		usleep(100);
1292 
1293 		rsp = ipmi_lan_recv_sol(intf); /* Grab the next packet */
1294 
1295 		if (sol_response_acks_packet(rsp, payload))
1296 			break;
1297 
1298 		else if (is_sol_packet(rsp) && rsp->data_len)
1299 		{
1300 			/*
1301 			 * We're still waiting for our ACK, but we more data from
1302 			 * the BMC
1303 			 */
1304 			intf->session->sol_data.sol_input_handler(rsp);
1305 		}
1306 
1307 		usleep(5000);
1308 		if (++try >= intf->ssn_params.retry) {
1309 			lprintf(LOG_DEBUG, "  No response from remote controller");
1310 			break;
1311 		}
1312 	}
1313 
1314 	if (msg != NULL) {
1315 		free(msg);
1316 		msg = NULL;
1317 	}
1318 	return rsp;
1319 }
1320 
1321 /*
1322  * is_sol_partial_ack
1323  *
1324  * Determine if the response is a partial ACK/NACK that indicates
1325  * we need to resend part of our packet.
1326  *
1327  * returns the number of characters we need to resend, or
1328  *         0 if this isn't an ACK or we don't need to resend anything
1329  */
1330 static int is_sol_partial_ack(struct ipmi_v2_payload * v2_payload,
1331 			      struct ipmi_rs         * rsp)
1332 {
1333 	int chars_to_resend = 0;
1334 
1335 	if (v2_payload                                &&
1336 	    rsp                                       &&
1337 	    is_sol_packet(rsp)                        &&
1338 	    sol_response_acks_packet(rsp, v2_payload) &&
1339 	    (rsp->payload.sol_packet.accepted_character_count <
1340 	     v2_payload->payload.sol_packet.character_count))
1341 	{
1342 		if (rsp->payload.sol_packet.accepted_character_count == 0) {
1343 			/* We should not resend data */
1344 			chars_to_resend = 0;
1345 		}
1346 		else
1347 		{
1348 			chars_to_resend =
1349 				v2_payload->payload.sol_packet.character_count -
1350 				rsp->payload.sol_packet.accepted_character_count;
1351 		}
1352 	}
1353 
1354 	return chars_to_resend;
1355 }
1356 
1357 /*
1358  * set_sol_packet_sequence_number
1359  */
1360 static void set_sol_packet_sequence_number(struct ipmi_intf * intf,
1361 					   struct ipmi_v2_payload * v2_payload)
1362 {
1363 	/* Keep our sequence number sane */
1364 	if (intf->session->sol_data.sequence_number > 0x0F)
1365 		intf->session->sol_data.sequence_number = 1;
1366 
1367 	v2_payload->payload.sol_packet.packet_sequence_number =
1368 		intf->session->sol_data.sequence_number++;
1369 }
1370 
1371 /*
1372  * ipmi_lan_send_sol
1373  *
1374  * Sends a SOL packet..  We handle partial ACK/NACKs from the BMC here.
1375  *
1376  * Returns a pointer to the SOL ACK we received, or
1377  *         0 on failure
1378  *
1379  */
1380 struct ipmi_rs *
1381 ipmi_lan_send_sol(struct ipmi_intf * intf,
1382 		  struct ipmi_v2_payload * v2_payload)
1383 {
1384 	struct ipmi_rs * rsp;
1385 	int chars_to_resend = 0;
1386 
1387 	v2_payload->payload_type   = IPMI_PAYLOAD_TYPE_SOL;
1388 
1389 	/*
1390 	 * Payload length is just the length of the character
1391 	 * data here.
1392 	 */
1393 	v2_payload->payload.sol_packet.acked_packet_number = 0; /* NA */
1394 
1395 	set_sol_packet_sequence_number(intf, v2_payload);
1396 
1397 	v2_payload->payload.sol_packet.accepted_character_count = 0; /* NA */
1398 
1399 	rsp = ipmi_lan_send_sol_payload(intf, v2_payload);
1400 
1401 	/* Determine if we need to resend some of our data */
1402 	chars_to_resend = is_sol_partial_ack(v2_payload, rsp);
1403 
1404 	while (chars_to_resend)
1405 	{
1406 		/*
1407 		 * We first need to handle any new data we might have
1408 		 * received in our NACK
1409 		 */
1410 		if (rsp->data_len)
1411 			intf->session->sol_data.sol_input_handler(rsp);
1412 
1413 		set_sol_packet_sequence_number(intf, v2_payload);
1414 
1415 		/* Just send the required data */
1416 		memmove(v2_payload->payload.sol_packet.data,
1417 			v2_payload->payload.sol_packet.data +
1418 			rsp->payload.sol_packet.accepted_character_count,
1419 			chars_to_resend);
1420 
1421 		v2_payload->payload.sol_packet.character_count = chars_to_resend;
1422 
1423 		rsp = ipmi_lan_send_sol_payload(intf, v2_payload);
1424 
1425 		chars_to_resend = is_sol_partial_ack(v2_payload, rsp);
1426 	}
1427 
1428 	return rsp;
1429 }
1430 
1431 /*
1432  * check_sol_packet_for_new_data
1433  *
1434  * Determine whether the SOL packet has already been seen
1435  * and whether the packet has new data for us.
1436  *
1437  * This function has the side effect of removing an previously
1438  * seen data, and moving new data to the front.
1439  *
1440  * It also "Remembers" the data so we don't get repeats.
1441  *
1442  */
1443 static int
1444 check_sol_packet_for_new_data(struct ipmi_intf * intf,
1445 			      struct ipmi_rs *rsp)
1446 {
1447 	static uint8_t last_received_sequence_number = 0;
1448 	static uint8_t last_received_byte_count      = 0;
1449 	int new_data_size                            = 0;
1450 
1451 	if (rsp &&
1452 	    (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL))
1453 
1454 	{
1455 		uint8_t unaltered_data_len = rsp->data_len;
1456 		if (rsp->payload.sol_packet.packet_sequence_number ==
1457 		    last_received_sequence_number)
1458 		{
1459 			/*
1460 			 * This is the same as the last packet, but may include
1461 			 * extra data
1462 			 */
1463 			new_data_size = rsp->data_len - last_received_byte_count;
1464 
1465 			if (new_data_size > 0)
1466 			{
1467 				/* We have more data to process */
1468 				memmove(rsp->data,
1469 					rsp->data +
1470 					rsp->data_len - new_data_size,
1471 					new_data_size);
1472 			}
1473 
1474 			rsp->data_len = new_data_size;
1475 		}
1476 
1477 		/*
1478 		 *Rember the data for next round
1479 		 */
1480 		if (rsp && rsp->payload.sol_packet.packet_sequence_number)
1481 		{
1482 			last_received_sequence_number =
1483 				rsp->payload.sol_packet.packet_sequence_number;
1484 			last_received_byte_count = unaltered_data_len;
1485 		}
1486 	}
1487 
1488 	return new_data_size;
1489 }
1490 
1491 /*
1492  * ack_sol_packet
1493  *
1494  * Provided the specified packet looks reasonable, ACK it.
1495  */
1496 static void
1497 ack_sol_packet(struct ipmi_intf * intf,
1498 	       struct ipmi_rs * rsp)
1499 {
1500 	if (rsp &&
1501 	    (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) &&
1502 	    (rsp->payload.sol_packet.packet_sequence_number))
1503 	{
1504 		struct ipmi_v2_payload ack;
1505 
1506 		memset(&ack, 0, sizeof(struct ipmi_v2_payload));
1507 
1508 		ack.payload_type = IPMI_PAYLOAD_TYPE_SOL;
1509 
1510 		/*
1511 		 * Payload length is just the length of the character
1512 		 * data here.
1513 		 */
1514 		ack.payload_length = 0;
1515 
1516 		/* ACK packets have sequence numbers of 0 */
1517 		ack.payload.sol_packet.packet_sequence_number = 0;
1518 
1519 		ack.payload.sol_packet.acked_packet_number =
1520 			rsp->payload.sol_packet.packet_sequence_number;
1521 
1522 		ack.payload.sol_packet.accepted_character_count = rsp->data_len;
1523 
1524 		ipmi_lan_send_sol_payload(intf, &ack);
1525 	}
1526 }
1527 
1528 /*
1529  * ipmi_recv_sol
1530  *
1531  * Receive a SOL packet and send an ACK in response.
1532  *
1533  */
1534 static struct ipmi_rs *
1535 ipmi_lan_recv_sol(struct ipmi_intf * intf)
1536 {
1537 	struct ipmi_rs * rsp = ipmi_lan_poll_recv(intf);
1538 
1539 	ack_sol_packet(intf, rsp);
1540 
1541 	/*
1542 	 * Remembers the data sent, and alters the data to just
1543 	 * include the new stuff.
1544 	 */
1545 	check_sol_packet_for_new_data(intf, rsp);
1546 
1547 	return rsp;
1548 }
1549 
1550 /* send a get device id command to keep session active */
1551 static int
1552 ipmi_lan_keepalive(struct ipmi_intf * intf)
1553 {
1554 	struct ipmi_rs * rsp;
1555 	struct ipmi_rq req = {
1556 		.msg = {
1557 			.netfn = IPMI_NETFN_APP,
1558 			.cmd = 1,
1559 		}
1560 	};
1561 
1562 	if (!intf->opened)
1563 		return 0;
1564 
1565 	rsp = intf->sendrecv(intf, &req);
1566 	if (rsp == NULL)
1567 		return -1;
1568 	if (rsp->ccode > 0)
1569 		return -1;
1570 
1571 	return 0;
1572 }
1573 
1574 /*
1575  * IPMI Get Channel Authentication Capabilities Command
1576  */
1577 static int
1578 ipmi_get_auth_capabilities_cmd(struct ipmi_intf * intf)
1579 {
1580 	struct ipmi_rs * rsp;
1581 	struct ipmi_rq req;
1582 	struct ipmi_session * s = intf->session;
1583 	struct ipmi_session_params *p = &intf->ssn_params;
1584 	uint8_t msg_data[2];
1585 
1586 	msg_data[0] = IPMI_LAN_CHANNEL_E;
1587 	msg_data[1] = p->privlvl;
1588 
1589 	memset(&req, 0, sizeof(req));
1590 	req.msg.netfn    = IPMI_NETFN_APP;
1591 	req.msg.cmd      = 0x38;
1592 	req.msg.data     = msg_data;
1593 	req.msg.data_len = 2;
1594 
1595 	rsp = intf->sendrecv(intf, &req);
1596 	if (rsp == NULL) {
1597 		lprintf(LOG_INFO, "Get Auth Capabilities command failed");
1598 		return -1;
1599 	}
1600 	if (verbose > 2)
1601 		printbuf(rsp->data, rsp->data_len, "get_auth_capabilities");
1602 
1603 	if (rsp->ccode > 0) {
1604 		lprintf(LOG_INFO, "Get Auth Capabilities command failed: %s",
1605 			val2str(rsp->ccode, completion_code_vals));
1606 		return -1;
1607 	}
1608 
1609 	lprintf(LOG_DEBUG, "Channel %02x Authentication Capabilities:",
1610 		rsp->data[0]);
1611 	lprintf(LOG_DEBUG, "  Privilege Level : %s",
1612 		val2str(req.msg.data[1], ipmi_privlvl_vals));
1613 	lprintf(LOG_DEBUG, "  Auth Types      : %s%s%s%s%s",
1614 		(rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_NONE) ? "NONE " : "",
1615 		(rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD2) ? "MD2 " : "",
1616 		(rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD5) ? "MD5 " : "",
1617 		(rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD) ? "PASSWORD " : "",
1618 		(rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_OEM) ? "OEM " : "");
1619 	lprintf(LOG_DEBUG, "  Per-msg auth    : %sabled",
1620 		(rsp->data[2] & IPMI_AUTHSTATUS_PER_MSG_DISABLED) ?
1621 		"dis" : "en");
1622 	lprintf(LOG_DEBUG, "  User level auth : %sabled",
1623 		(rsp->data[2] & IPMI_AUTHSTATUS_PER_USER_DISABLED) ?
1624 		"dis" : "en");
1625 	lprintf(LOG_DEBUG, "  Non-null users  : %sabled",
1626 		(rsp->data[2] & IPMI_AUTHSTATUS_NONNULL_USERS_ENABLED) ?
1627 		"en" : "dis");
1628 	lprintf(LOG_DEBUG, "  Null users      : %sabled",
1629 		(rsp->data[2] & IPMI_AUTHSTATUS_NULL_USERS_ENABLED) ?
1630 		"en" : "dis");
1631 	lprintf(LOG_DEBUG, "  Anonymous login : %sabled",
1632 		(rsp->data[2] & IPMI_AUTHSTATUS_ANONYMOUS_USERS_ENABLED) ?
1633 		"en" : "dis");
1634 	lprintf(LOG_DEBUG, "");
1635 
1636 	s->authstatus = rsp->data[2];
1637 
1638 	if (p->password &&
1639 	    (p->authtype_set == 0 ||
1640 	     p->authtype_set == IPMI_SESSION_AUTHTYPE_MD5) &&
1641 	    (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD5))
1642 	{
1643 		s->authtype = IPMI_SESSION_AUTHTYPE_MD5;
1644 	}
1645 	else if (p->password &&
1646 		 (p->authtype_set == 0 ||
1647 		  p->authtype_set == IPMI_SESSION_AUTHTYPE_MD2) &&
1648 		 (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD2))
1649 	{
1650 		s->authtype = IPMI_SESSION_AUTHTYPE_MD2;
1651 	}
1652 	else if (p->password &&
1653 		 (p->authtype_set == 0 ||
1654 		  p->authtype_set == IPMI_SESSION_AUTHTYPE_PASSWORD) &&
1655 		 (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD))
1656 	{
1657 		s->authtype = IPMI_SESSION_AUTHTYPE_PASSWORD;
1658 	}
1659 	else if (p->password &&
1660 		 (p->authtype_set == 0 ||
1661 		  p->authtype_set == IPMI_SESSION_AUTHTYPE_OEM) &&
1662 		 (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_OEM))
1663 	{
1664 		s->authtype = IPMI_SESSION_AUTHTYPE_OEM;
1665 	}
1666 	else if ((p->authtype_set == 0 ||
1667 		  p->authtype_set == IPMI_SESSION_AUTHTYPE_NONE) &&
1668 		 (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_NONE))
1669 	{
1670 		s->authtype = IPMI_SESSION_AUTHTYPE_NONE;
1671 	}
1672 	else {
1673 		if (!(rsp->data[1] & 1<<p->authtype_set))
1674 			lprintf(LOG_ERR, "Authentication type %s not supported",
1675 			       val2str(p->authtype_set, ipmi_authtype_session_vals));
1676 		else
1677 			lprintf(LOG_ERR, "No supported authtypes found");
1678 
1679 		return -1;
1680 	}
1681 
1682 	lprintf(LOG_DEBUG, "Proceeding with AuthType %s",
1683 		val2str(s->authtype, ipmi_authtype_session_vals));
1684 
1685 	return 0;
1686 }
1687 
1688 /*
1689  * IPMI Get Session Challenge Command
1690  * returns a temporary session ID and 16 byte challenge string
1691  */
1692 static int
1693 ipmi_get_session_challenge_cmd(struct ipmi_intf * intf)
1694 {
1695 	struct ipmi_rs * rsp;
1696 	struct ipmi_rq req;
1697 	struct ipmi_session * s = intf->session;
1698 	uint8_t msg_data[17];
1699 
1700 	memset(msg_data, 0, 17);
1701 	msg_data[0] = s->authtype;
1702 	memcpy(msg_data+1, intf->ssn_params.username, 16);
1703 
1704 	memset(&req, 0, sizeof(req));
1705 	req.msg.netfn		= IPMI_NETFN_APP;
1706 	req.msg.cmd		= 0x39;
1707 	req.msg.data		= msg_data;
1708 	req.msg.data_len	= 17; /* 1 byte for authtype, 16 for user */
1709 
1710 	rsp = intf->sendrecv(intf, &req);
1711 	if (rsp == NULL) {
1712 		lprintf(LOG_ERR, "Get Session Challenge command failed");
1713 		return -1;
1714 	}
1715 	if (verbose > 2)
1716 		printbuf(rsp->data, rsp->data_len, "get_session_challenge");
1717 
1718 	if (rsp->ccode > 0) {
1719 		switch (rsp->ccode) {
1720 		case 0x81:
1721 			lprintf(LOG_ERR, "Invalid user name");
1722 			break;
1723 		case 0x82:
1724 			lprintf(LOG_ERR, "NULL user name not enabled");
1725 			break;
1726 		default:
1727 			lprintf(LOG_ERR, "Get Session Challenge command failed: %s",
1728 				val2str(rsp->ccode, completion_code_vals));
1729 		}
1730 		return -1;
1731 	}
1732 
1733 	memcpy(&s->session_id, rsp->data, 4);
1734 	memcpy(s->challenge, rsp->data + 4, 16);
1735 
1736 	lprintf(LOG_DEBUG, "Opening Session");
1737 	lprintf(LOG_DEBUG, "  Session ID      : %08lx", (long)s->session_id);
1738 	lprintf(LOG_DEBUG, "  Challenge       : %s", buf2str(s->challenge, 16));
1739 
1740 	return 0;
1741 }
1742 
1743 /*
1744  * IPMI Activate Session Command
1745  */
1746 static int
1747 ipmi_activate_session_cmd(struct ipmi_intf * intf)
1748 {
1749 	struct ipmi_rs * rsp;
1750 	struct ipmi_rq req;
1751 	struct ipmi_session * s = intf->session;
1752 	uint8_t msg_data[22];
1753 
1754 	memset(&req, 0, sizeof(req));
1755 	req.msg.netfn = IPMI_NETFN_APP;
1756 	req.msg.cmd = 0x3a;
1757 
1758 	msg_data[0] = s->authtype;
1759 	msg_data[1] = intf->ssn_params.privlvl;
1760 
1761 	/* supermicro oem authentication hack */
1762 	if (ipmi_oem_active(intf, "supermicro")) {
1763 		uint8_t * special = ipmi_auth_special(s);
1764 		memcpy(intf->session->authcode, special, 16);
1765 		memset(msg_data + 2, 0, 16);
1766 		lprintf(LOG_DEBUG, "  OEM Auth        : %s",
1767 			buf2str(special, 16));
1768 	} else {
1769 		memcpy(msg_data + 2, s->challenge, 16);
1770 	}
1771 
1772 	/* setup initial outbound sequence number */
1773 	get_random(msg_data+18, 4);
1774 
1775 	req.msg.data = msg_data;
1776 	req.msg.data_len = 22;
1777 
1778 	s->active = 1;
1779 
1780 	lprintf(LOG_DEBUG, "  Privilege Level : %s",
1781 		val2str(msg_data[1], ipmi_privlvl_vals));
1782 	lprintf(LOG_DEBUG, "  Auth Type       : %s",
1783 		val2str(s->authtype, ipmi_authtype_session_vals));
1784 
1785 	rsp = intf->sendrecv(intf, &req);
1786 	if (rsp == NULL) {
1787 		lprintf(LOG_ERR, "Activate Session command failed");
1788 		s->active = 0;
1789 		return -1;
1790 	}
1791 	if (verbose > 2)
1792 		printbuf(rsp->data, rsp->data_len, "activate_session");
1793 
1794 	if (rsp->ccode) {
1795 		fprintf(stderr, "Activate Session error:");
1796 		switch (rsp->ccode) {
1797 		case 0x81:
1798 			lprintf(LOG_ERR, "\tNo session slot available");
1799 			break;
1800 		case 0x82:
1801 			lprintf(LOG_ERR, "\tNo slot available for given user - "
1802 				"limit reached");
1803 			break;
1804 		case 0x83:
1805 			lprintf(LOG_ERR, "\tNo slot available to support user "
1806 				"due to maximum privilege capacity");
1807 			break;
1808 		case 0x84:
1809 			lprintf(LOG_ERR, "\tSession sequence out of range");
1810 			break;
1811 		case 0x85:
1812 			lprintf(LOG_ERR, "\tInvalid session ID in request");
1813 			break;
1814 		case 0x86:
1815 			lprintf(LOG_ERR, "\tRequested privilege level "
1816 				"exceeds limit");
1817 			break;
1818 		case 0xd4:
1819 			lprintf(LOG_ERR, "\tInsufficient privilege level");
1820 			break;
1821 		default:
1822 			lprintf(LOG_ERR, "\t%s",
1823 				val2str(rsp->ccode, completion_code_vals));
1824 		}
1825 		return -1;
1826 	}
1827 
1828 	memcpy(&s->session_id, rsp->data + 1, 4);
1829 	s->in_seq = rsp->data[8] << 24 | rsp->data[7] << 16 | rsp->data[6] << 8 | rsp->data[5];
1830 	if (s->in_seq == 0)
1831 		++s->in_seq;
1832 
1833 	if (s->authstatus & IPMI_AUTHSTATUS_PER_MSG_DISABLED)
1834 		s->authtype = IPMI_SESSION_AUTHTYPE_NONE;
1835 	else if (s->authtype != (rsp->data[0] & 0xf)) {
1836 		lprintf(LOG_ERR, "Invalid Session AuthType %s in response",
1837 			val2str(s->authtype, ipmi_authtype_session_vals));
1838 		return -1;
1839 	}
1840 
1841 	lprintf(LOG_DEBUG, "\nSession Activated");
1842 	lprintf(LOG_DEBUG, "  Auth Type       : %s",
1843 		val2str(rsp->data[0], ipmi_authtype_session_vals));
1844 	lprintf(LOG_DEBUG, "  Max Priv Level  : %s",
1845 		val2str(rsp->data[9], ipmi_privlvl_vals));
1846 	lprintf(LOG_DEBUG, "  Session ID      : %08lx", (long)s->session_id);
1847 	lprintf(LOG_DEBUG, "  Inbound Seq     : %08lx\n", (long)s->in_seq);
1848 
1849 	return 0;
1850 }
1851 
1852 
1853 /*
1854  * IPMI Set Session Privilege Level Command
1855  */
1856 static int
1857 ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf)
1858 {
1859 	struct ipmi_rs * rsp;
1860 	struct ipmi_rq req;
1861 	uint8_t privlvl = intf->ssn_params.privlvl;
1862 	uint8_t backup_bridge_possible = bridge_possible;
1863 
1864 	if (privlvl <= IPMI_SESSION_PRIV_USER)
1865 		return 0;	/* no need to set higher */
1866 
1867 	memset(&req, 0, sizeof(req));
1868 	req.msg.netfn		= IPMI_NETFN_APP;
1869 	req.msg.cmd		= 0x3b;
1870 	req.msg.data		= &privlvl;
1871 	req.msg.data_len	= 1;
1872 
1873 	bridge_possible = 0;
1874 	rsp = intf->sendrecv(intf, &req);
1875 	bridge_possible = backup_bridge_possible;
1876 
1877 	if (rsp == NULL) {
1878 		lprintf(LOG_ERR, "Set Session Privilege Level to %s failed",
1879 			val2str(privlvl, ipmi_privlvl_vals));
1880 		return -1;
1881 	}
1882 	if (verbose > 2)
1883 		printbuf(rsp->data, rsp->data_len, "set_session_privlvl");
1884 
1885 	if (rsp->ccode > 0) {
1886 		lprintf(LOG_ERR, "Set Session Privilege Level to %s failed: %s",
1887 			val2str(privlvl, ipmi_privlvl_vals),
1888 			val2str(rsp->ccode, completion_code_vals));
1889 		return -1;
1890 	}
1891 
1892 	lprintf(LOG_DEBUG, "Set Session Privilege Level to %s\n",
1893 		val2str(rsp->data[0], ipmi_privlvl_vals));
1894 
1895 	return 0;
1896 }
1897 
1898 static int
1899 ipmi_close_session_cmd(struct ipmi_intf * intf)
1900 {
1901 	struct ipmi_rs * rsp;
1902 	struct ipmi_rq req;
1903 	uint8_t msg_data[4];
1904 	uint32_t session_id = intf->session->session_id;
1905 
1906 	if (intf->session->active == 0)
1907 		return -1;
1908 
1909 	intf->target_addr = IPMI_BMC_SLAVE_ADDR;
1910 	bridge_possible = 0;  /* Not a bridge message */
1911 
1912 	memcpy(&msg_data, &session_id, 4);
1913 
1914 	memset(&req, 0, sizeof(req));
1915 	req.msg.netfn		= IPMI_NETFN_APP;
1916 	req.msg.cmd		= 0x3c;
1917 	req.msg.data		= msg_data;
1918 	req.msg.data_len	= 4;
1919 
1920 	rsp = intf->sendrecv(intf, &req);
1921 	if (rsp == NULL) {
1922 		lprintf(LOG_ERR, "Close Session command failed");
1923 		return -1;
1924 	}
1925 	if (verbose > 2)
1926 		printbuf(rsp->data, rsp->data_len, "close_session");
1927 
1928 	if (rsp->ccode == 0x87) {
1929 		lprintf(LOG_ERR, "Failed to Close Session: invalid "
1930 			"session ID %08lx", (long)session_id);
1931 		return -1;
1932 	}
1933 	if (rsp->ccode > 0) {
1934 		lprintf(LOG_ERR, "Close Session command failed: %s",
1935 			val2str(rsp->ccode, completion_code_vals));
1936 		return -1;
1937 	}
1938 
1939 	lprintf(LOG_DEBUG, "Closed Session %08lx\n", (long)session_id);
1940 
1941 	return 0;
1942 }
1943 
1944 /*
1945  * IPMI LAN Session Activation (IPMI spec v1.5 section 12.9)
1946  *
1947  * 1. send "RMCP Presence Ping" message, response message will
1948  *    indicate whether the platform supports IPMI
1949  * 2. send "Get Channel Authentication Capabilities" command
1950  *    with AUTHTYPE = none, response packet will contain information
1951  *    about supported challenge/response authentication types
1952  * 3. send "Get Session Challenge" command with AUTHTYPE = none
1953  *    and indicate the authentication type in the message, response
1954  *    packet will contain challenge string and temporary session ID.
1955  * 4. send "Activate Session" command, authenticated with AUTHTYPE
1956  *    sent in previous message.  Also sends the initial value for
1957  *    the outbound sequence number for BMC.
1958  * 5. BMC returns response confirming session activation and
1959  *    session ID for this session and initial inbound sequence.
1960  */
1961 static int
1962 ipmi_lan_activate_session(struct ipmi_intf * intf)
1963 {
1964 	int rc;
1965 
1966 	/* don't fail on ping because its not always supported.
1967 	 * Supermicro's IPMI LAN 1.5 cards don't tolerate pings.
1968 	 */
1969 	if (!ipmi_oem_active(intf, "supermicro"))
1970 		ipmi_lan_ping(intf);
1971 
1972 	/* Some particular Intel boards need special help
1973 	 */
1974 	if (ipmi_oem_active(intf, "intelwv2"))
1975 		ipmi_lan_thump_first(intf);
1976 
1977 	rc = ipmi_get_auth_capabilities_cmd(intf);
1978 	if (rc < 0) {
1979 		goto fail;
1980 	}
1981 
1982 	rc = ipmi_get_session_challenge_cmd(intf);
1983 	if (rc < 0)
1984 		goto fail;
1985 
1986 	rc = ipmi_activate_session_cmd(intf);
1987 	if (rc < 0)
1988 		goto fail;
1989 
1990 	intf->abort = 0;
1991 
1992 	rc = ipmi_set_session_privlvl_cmd(intf);
1993 	if (rc < 0)
1994 		goto close_fail;
1995 
1996 	return 0;
1997 
1998  close_fail:
1999 	ipmi_close_session_cmd(intf);
2000  fail:
2001 	lprintf(LOG_ERR, "Error: Unable to establish LAN session");
2002 	return -1;
2003 }
2004 
2005 void
2006 ipmi_lan_close(struct ipmi_intf * intf)
2007 {
2008 	if (!intf->abort && intf->session)
2009 		ipmi_close_session_cmd(intf);
2010 
2011 	if (intf->fd >= 0) {
2012 		close(intf->fd);
2013 		intf->fd = -1;
2014 	}
2015 
2016 	ipmi_req_clear_entries();
2017 	ipmi_intf_session_cleanup(intf);
2018 	intf->opened = 0;
2019 	intf->manufacturer_id = IPMI_OEM_UNKNOWN;
2020 	intf = NULL;
2021 }
2022 
2023 static int
2024 ipmi_lan_open(struct ipmi_intf * intf)
2025 {
2026 	int rc;
2027 	struct ipmi_session *s;
2028 	struct ipmi_session_params *p;
2029 	struct sockaddr_storage addr;
2030 
2031 	if (intf == NULL || intf->opened)
2032 		return -1;
2033 
2034 	s = intf->session;
2035 	p = &intf->ssn_params;
2036 
2037 	if (p->port == 0)
2038 		p->port = IPMI_LAN_PORT;
2039 	if (p->privlvl == 0)
2040 		p->privlvl = IPMI_SESSION_PRIV_ADMIN;
2041 	if (p->timeout == 0)
2042 		p->timeout = IPMI_LAN_TIMEOUT;
2043 	if (p->retry == 0)
2044 		p->retry = IPMI_LAN_RETRY;
2045 
2046 	if (p->hostname == NULL || strlen((const char *)p->hostname) == 0) {
2047 		lprintf(LOG_ERR, "No hostname specified!");
2048 		return -1;
2049 	}
2050 
2051 	if (ipmi_intf_socket_connect(intf) == -1) {
2052 		lprintf(LOG_ERR, "Could not open socket!");
2053 		return -1;
2054 	}
2055 
2056 	s = (struct ipmi_session *)malloc(sizeof(struct ipmi_session));
2057 	if (!s) {
2058 		lprintf(LOG_ERR, "ipmitool: malloc failure");
2059 		goto fail;
2060 	}
2061 
2062 	intf->opened = 1;
2063 	intf->abort = 1;
2064 
2065 	intf->session = s;
2066 
2067 	memset(s, 0, sizeof(struct ipmi_session));
2068 	s->sol_data.sequence_number = 1;
2069 	s->timeout = p->timeout;
2070 	memcpy(&s->authcode, &p->authcode_set, sizeof(s->authcode));
2071 	s->addrlen = sizeof(s->addr);
2072 	if (getsockname(intf->fd, &s->addr, &s->addrlen)) {
2073 		goto fail;
2074 	}
2075 
2076 	/* try to open session */
2077 	rc = ipmi_lan_activate_session(intf);
2078 	if (rc < 0) {
2079 	    goto fail;
2080 	}
2081 
2082 	/* automatically detect interface request and response sizes */
2083 	hpm2_detect_max_payload_size(intf);
2084 
2085 	/* set manufactirer OEM id */
2086 	intf->manufacturer_id = ipmi_get_oem(intf);
2087 
2088 	/* now allow bridging */
2089 	bridge_possible = 1;
2090 	return intf->fd;
2091 
2092  fail:
2093 	lprintf(LOG_ERR, "Error: Unable to establish IPMI v1.5 / RMCP session");
2094 	intf->close(intf);
2095 	return -1;
2096 }
2097 
2098 static int
2099 ipmi_lan_setup(struct ipmi_intf * intf)
2100 {
2101 	/* setup default LAN maximum request and response sizes */
2102 	intf->max_request_data_size = IPMI_LAN_MAX_REQUEST_SIZE;
2103 	intf->max_response_data_size = IPMI_LAN_MAX_RESPONSE_SIZE;
2104 
2105 	return 0;
2106 }
2107 
2108 static void
2109 ipmi_lan_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size)
2110 {
2111 	if (size + 7 > 0xFF) {
2112 		size = 0xFF - 7;
2113 	}
2114 
2115 	intf->max_request_data_size = size;
2116 }
2117 
2118 static void
2119 ipmi_lan_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size)
2120 {
2121 	if (size + 8 > 0xFF) {
2122 		size = 0xFF - 8;
2123 	}
2124 
2125 	intf->max_response_data_size = size;
2126 }
2127