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