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