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