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