Print this page
NEX-9891 Unable to use ipmitopo to return IPMI data for ipmi-enabled JBODs
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/libipmi/common/ipmi_lan.c
+++ new/usr/src/lib/libipmi/common/ipmi_lan.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 + * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
24 25 */
25 26
26 27 #include <stdlib.h>
27 28 #include <stdio.h>
28 29 #include <assert.h>
29 30 #include <inttypes.h>
30 31 #include <string.h>
31 32 #include <sys/types.h>
32 33 #include <sys/socket.h>
33 34 #include <netinet/in.h>
34 35 #include <arpa/inet.h>
35 36 #include <errno.h>
36 37 #include <unistd.h>
37 38 #include <netdb.h>
38 39 #include <fcntl.h>
39 40
40 41 #include "libipmi.h"
41 42 #include "ipmi_lan.h"
42 43 #include "ipmi_impl.h"
43 44
44 45 #define DEF_IPMI_LAN_TIMEOUT 3 /* seconds */
45 46 #define DEF_IPMI_LAN_NUM_RETRIES 5
46 47 #define IPMI_LAN_CHANNEL_E 0x0e
47 48
48 49 typedef struct ipmi_rs {
49 50 uint8_t ir_data[IPMI_BUF_SIZE];
50 51 int ir_dlen;
51 52 ipmi_msg_hdr_t ir_ihdr;
52 53 uint8_t ir_ccode;
53 54 } ipmi_rs_t;
54 55
55 56 static ipmi_rs_t *ipmi_lan_poll_recv(ipmi_handle_t *);
56 57
57 58 typedef struct ipmi_rq_entry {
58 59 ipmi_list_t ire_list;
59 60 ipmi_cmd_t ire_req;
60 61 uint8_t ire_target_cmd;
61 62 uint8_t ire_rq_seq;
62 63 uint8_t *ire_msg_data;
63 64 int ire_msg_len;
64 65 } ipmi_rq_entry_t;
65 66
66 67 ipmi_rq_entry_t *ipmi_req_entries = NULL;
67 68
68 69 /*
69 70 * LAN transport-specific data
70 71 */
71 72 typedef struct ipmi_lan {
72 73 ipmi_handle_t *il_ihp;
73 74 char il_host[MAXHOSTNAMELEN + 1];
74 75 uint16_t il_port;
75 76 char il_user[17];
76 77 char il_authcode[IPMI_AUTHCODE_BUF_SIZE + 1];
77 78 uint8_t il_challenge[16];
78 79 uint32_t il_session_id;
79 80 int il_sd;
80 81 boolean_t il_send_authcode;
81 82 boolean_t il_session_active;
82 83 uint8_t il_authtype;
83 84 uint8_t il_privlvl;
84 85 uint8_t il_num_retries;
85 86 uint32_t il_in_seq;
86 87 uint32_t il_timeout;
87 88 struct sockaddr_in il_addr;
88 89 socklen_t il_addrlen;
89 90 } ipmi_lan_t;
90 91
91 92 /*
92 93 * Calculate and returns IPMI checksum
93 94 *
94 95 * Checksum algorithm is described in Section 13.8
95 96 *
96 97 * d: buffer to check
97 98 * s: position in buffer to start checksum from
98 99 */
99 100 static uint8_t
100 101 ipmi_csum(uint8_t *d, int s)
101 102 {
102 103 uint8_t c = 0;
103 104 for (; s > 0; s--, d++)
104 105 c += *d;
105 106 return (-c);
106 107 }
107 108
108 109 static ipmi_rq_entry_t *
109 110 ipmi_req_add_entry(ipmi_handle_t *ihp, ipmi_cmd_t *req)
110 111 {
111 112 ipmi_rq_entry_t *e;
112 113
113 114 if ((e = ipmi_zalloc(ihp, sizeof (ipmi_rq_entry_t))) == NULL)
114 115 return (NULL);
115 116
116 117 (void) memcpy(&e->ire_req, req, sizeof (ipmi_cmd_t));
117 118 ipmi_list_append(&ipmi_req_entries->ire_list, e);
118 119
119 120 return (e);
120 121 }
121 122
122 123 /*ARGSUSED*/
123 124 static ipmi_rq_entry_t *
124 125 ipmi_req_lookup_entry(ipmi_handle_t *ihp, uint8_t seq, uint8_t cmd)
125 126 {
126 127 ipmi_rq_entry_t *e;
127 128
128 129 for (e = ipmi_list_next(&ipmi_req_entries->ire_list); e != NULL;
129 130 e = ipmi_list_next(e))
130 131 if (e->ire_rq_seq == seq && e->ire_req.ic_cmd == cmd)
131 132 return (e);
132 133
133 134 return (NULL);
134 135 }
135 136
136 137 static void
137 138 ipmi_req_remove_entry(ipmi_handle_t *ihp, uint8_t seq, uint8_t cmd)
138 139 {
139 140 ipmi_rq_entry_t *e;
140 141
141 142 e = ipmi_req_lookup_entry(ihp, seq, cmd);
142 143
143 144 if (e) {
144 145 ipmi_list_delete(&ipmi_req_entries->ire_list, e);
145 146 ipmi_free(ihp, e->ire_msg_data);
146 147 ipmi_free(ihp, e);
147 148 }
148 149 }
149 150
150 151 static void
151 152 ipmi_req_clear_entries(ipmi_handle_t *ihp)
152 153 {
153 154 ipmi_rq_entry_t *e;
154 155
155 156 while ((e = ipmi_list_next(&ipmi_req_entries->ire_list)) != NULL) {
156 157 ipmi_list_delete(&ipmi_req_entries->ire_list, e);
157 158 ipmi_free(ihp, e);
158 159 }
159 160 }
160 161
161 162 static int
162 163 get_random(void *buf, uint_t len)
163 164 {
164 165 int fd;
165 166
166 167 assert(buf != NULL && len > 0);
167 168 if ((fd = open("/dev/urandom", O_RDONLY)) < 0)
168 169 return (-1);
169 170
170 171 if (read(fd, buf, len) < 0) {
171 172 (void) close(fd);
172 173 return (-1);
173 174 }
174 175 (void) close(fd);
175 176 return (0);
176 177 }
177 178
178 179 static int
179 180 ipmi_lan_send_packet(ipmi_handle_t *ihp, uint8_t *data, int dlen)
180 181 {
181 182 ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata;
182 183
183 184 return (send(ilp->il_sd, data, dlen, 0));
184 185 }
185 186
186 187 static ipmi_rs_t *
187 188 ipmi_lan_recv_packet(ipmi_handle_t *ihp)
188 189 {
189 190 static ipmi_rs_t rsp;
190 191 fd_set read_set, err_set;
191 192 struct timeval tmout;
192 193 ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata;
193 194 int ret;
194 195
195 196 FD_ZERO(&read_set);
196 197 FD_SET(ilp->il_sd, &read_set);
197 198
198 199 FD_ZERO(&err_set);
199 200 FD_SET(ilp->il_sd, &err_set);
200 201
201 202 tmout.tv_sec = ilp->il_timeout;
202 203 tmout.tv_usec = 0;
203 204
204 205 ret = select(ilp->il_sd + 1, &read_set, NULL, &err_set, &tmout);
205 206 if (ret < 0 || FD_ISSET(ilp->il_sd, &err_set) ||
206 207 !FD_ISSET(ilp->il_sd, &read_set))
207 208 return (NULL);
208 209
209 210 /*
210 211 * The first read may return ECONNREFUSED because the rmcp ping
211 212 * packet--sent to UDP port 623--will be processed by both the
212 213 * BMC and the OS.
213 214 *
214 215 * The problem with this is that the ECONNREFUSED takes
215 216 * priority over any other received datagram; that means that
216 217 * the Connection Refused shows up _before_ the response packet,
217 218 * regardless of the order they were sent out. (unless the
218 219 * response is read before the connection refused is returned)
219 220 */
220 221 ret = recv(ilp->il_sd, &rsp.ir_data, IPMI_BUF_SIZE, 0);
221 222
222 223 if (ret < 0) {
223 224 FD_ZERO(&read_set);
224 225 FD_SET(ilp->il_sd, &read_set);
225 226
226 227 FD_ZERO(&err_set);
227 228 FD_SET(ilp->il_sd, &err_set);
228 229
229 230 tmout.tv_sec = ilp->il_timeout;
230 231 tmout.tv_usec = 0;
231 232
232 233 ret = select(ilp->il_sd + 1, &read_set, NULL, &err_set, &tmout);
233 234 if (ret < 0) {
234 235 if (FD_ISSET(ilp->il_sd, &err_set) ||
235 236 !FD_ISSET(ilp->il_sd, &read_set))
236 237 return (NULL);
237 238
238 239 ret = recv(ilp->il_sd, &rsp.ir_data, IPMI_BUF_SIZE, 0);
239 240 if (ret < 0)
240 241 return (NULL);
241 242 }
242 243 }
243 244
244 245 if (ret == 0)
245 246 return (NULL);
246 247
247 248 rsp.ir_data[ret] = '\0';
248 249 rsp.ir_dlen = ret;
249 250
250 251 return (&rsp);
251 252 }
252 253
253 254
254 255 /*
255 256 * ASF/RMCP Pong Message
256 257 *
257 258 * See section 13.2.4
258 259 */
259 260 struct rmcp_pong {
260 261 rmcp_hdr_t rp_rmcp;
261 262 asf_hdr_t rp_asf;
262 263 uint32_t rp_iana;
263 264 uint32_t rp_oem;
264 265 uint8_t rp_sup_entities;
265 266 uint8_t rp_sup_interact;
266 267 uint8_t rp_reserved[6];
267 268 };
268 269
269 270 /*
270 271 * parse response RMCP "pong" packet
271 272 *
272 273 * return -1 if ping response not received
273 274 * returns 0 if IPMI is NOT supported
274 275 * returns 1 if IPMI is supported
275 276 */
276 277 /*ARGSUSED*/
277 278 static int
278 279 ipmi_handle_pong(ipmi_handle_t *ihp, ipmi_rs_t *rsp)
279 280 {
280 281 struct rmcp_pong *pong;
281 282
282 283 if (rsp == NULL)
283 284 return (-1);
284 285
285 286 /*LINTED: E_BAD_PTR_CAST_ALIGN*/
286 287 pong = (struct rmcp_pong *)rsp->ir_data;
287 288
288 289 return ((pong->rp_sup_entities & 0x80) ? 1 : 0);
289 290 }
290 291
291 292 /*
292 293 * Build and send RMCP presence ping message
293 294 */
294 295 static int
295 296 ipmi_lan_ping(ipmi_handle_t *ihp)
296 297 {
297 298 rmcp_hdr_t rmcp_ping;
298 299 asf_hdr_t asf_ping;
299 300 uint8_t *data;
300 301 int rv, dlen = sizeof (rmcp_ping) + sizeof (asf_ping);
301 302
302 303 (void) memset(&rmcp_ping, 0, sizeof (rmcp_ping));
303 304 rmcp_ping.rh_version = RMCP_VERSION_1;
304 305 rmcp_ping.rh_msg_class = RMCP_CLASS_ASF;
305 306 rmcp_ping.rh_seq = 0xff;
306 307
307 308 (void) memset(&asf_ping, 0, sizeof (asf_ping));
308 309 asf_ping.ah_iana = htonl(ASF_RMCP_IANA);
309 310 asf_ping.ah_msg_type = ASF_TYPE_PING;
310 311
311 312 if ((data = ipmi_zalloc(ihp, dlen)) == NULL)
312 313 return (-1);
313 314
314 315 (void) memcpy(data, &rmcp_ping, sizeof (rmcp_ping));
315 316 (void) memcpy(data + sizeof (rmcp_ping), &asf_ping, sizeof (asf_ping));
316 317
317 318 rv = ipmi_lan_send_packet(ihp, data, dlen);
318 319
319 320 ipmi_free(ihp, data);
320 321
321 322 if (rv < 0)
322 323 return (ipmi_set_error(ihp, EIPMI_LAN_PING_FAILED, NULL));
323 324
324 325 if (ipmi_lan_poll_recv(ihp) == NULL)
325 326 return (ipmi_set_error(ihp, EIPMI_LAN_PING_FAILED, NULL));
326 327
327 328 return (0);
328 329 }
329 330
330 331 static ipmi_rs_t *
331 332 ipmi_lan_poll_recv(ipmi_handle_t *ihp)
332 333 {
333 334 rmcp_hdr_t rmcp_rsp;
334 335 ipmi_rs_t *rsp;
335 336 ipmi_rq_entry_t *entry;
336 337 int off = 0, rv;
337 338 ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata;
338 339 uint8_t rsp_authtype;
339 340
340 341 rsp = ipmi_lan_recv_packet(ihp);
341 342
342 343 while (rsp != NULL) {
343 344
344 345 /* parse response headers */
345 346 (void) memcpy(&rmcp_rsp, rsp->ir_data, 4);
346 347
347 348 switch (rmcp_rsp.rh_msg_class) {
348 349 case RMCP_CLASS_ASF:
349 350 /* ping response packet */
350 351 rv = ipmi_handle_pong(ihp, rsp);
351 352 return ((rv <= 0) ? NULL : rsp);
352 353 case RMCP_CLASS_IPMI:
353 354 /* handled by rest of function */
354 355 break;
355 356 default:
356 357 /* Invalid RMCP class */
357 358 rsp = ipmi_lan_recv_packet(ihp);
358 359 continue;
359 360 }
360 361
361 362 off = sizeof (rmcp_hdr_t);
362 363 rsp_authtype = rsp->ir_data[off];
363 364 if (ilp->il_send_authcode && (rsp_authtype || ilp->il_authtype))
364 365 off += 26;
365 366 else
366 367 off += 10;
367 368
368 369 (void) memcpy(&rsp->ir_ihdr, (void *)(rsp->ir_data + off),
369 370 sizeof (rsp->ir_ihdr));
370 371 rsp->ir_ihdr.imh_seq = rsp->ir_ihdr.imh_seq >> 2;
371 372 off += sizeof (rsp->ir_ihdr);
372 373 rsp->ir_ccode = rsp->ir_data[off++];
373 374
374 375 entry = ipmi_req_lookup_entry(ihp, rsp->ir_ihdr.imh_seq,
375 376 rsp->ir_ihdr.imh_cmd);
376 377 if (entry) {
377 378 ipmi_req_remove_entry(ihp, rsp->ir_ihdr.imh_seq,
378 379 rsp->ir_ihdr.imh_cmd);
379 380 } else {
380 381 rsp = ipmi_lan_recv_packet(ihp);
381 382 continue;
382 383 }
383 384 break;
384 385 }
385 386
386 387 /* shift response data to start of array */
387 388 if (rsp && rsp->ir_dlen > off) {
388 389 rsp->ir_dlen -= off + 1;
389 390 (void) memmove(rsp->ir_data, rsp->ir_data + off, rsp->ir_dlen);
390 391 (void) memset(rsp->ir_data + rsp->ir_dlen, 0,
391 392 IPMI_BUF_SIZE - rsp->ir_dlen);
392 393 }
393 394 return (rsp);
394 395 }
395 396
396 397 /*
397 398 * IPMI LAN Request Message Format
398 399 *
399 400 * See section 13.8
400 401 *
401 402 * +---------------------+
402 403 * | rmcp_hdr_t | 4 bytes
403 404 * +---------------------+
404 405 * | v15_session_hdr_t | 9 bytes
405 406 * +---------------------+
406 407 * | [authcode] | 16 bytes (if AUTHTYPE != none)
407 408 * +---------------------+
408 409 * | msg length | 1 byte
409 410 * +---------------------+
410 411 * | ipmi_msg_hdr_t | 6 bytes
411 412 * +---------------------+
412 413 * | [msg data] | variable
413 414 * +---------------------+
414 415 * | msg data checksum | 1 byte
415 416 * +---------------------+
416 417 */
417 418 static ipmi_rq_entry_t *
418 419 ipmi_lan_build_cmd(ipmi_handle_t *ihp, ipmi_cmd_t *req)
419 420 {
420 421 ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata;
421 422 rmcp_hdr_t rmcp_hdr;
422 423 v15_session_hdr_t session_hdr;
423 424 ipmi_msg_hdr_t msg_hdr;
424 425 uint8_t *msg;
425 426 int cs, tmp, off = 0, len;
426 427 ipmi_rq_entry_t *entry;
427 428 static int curr_seq = 0;
428 429
429 430 if (curr_seq >= 64)
430 431 curr_seq = 0;
431 432
432 433 if ((entry = ipmi_req_add_entry(ihp, req)) == NULL)
433 434 return (NULL);
434 435
435 436 len = req->ic_dlen + 29;
436 437 if (ilp->il_send_authcode && ilp->il_authtype)
437 438 len += 16;
438 439
439 440 if ((msg = ipmi_zalloc(ihp, len)) == NULL)
440 441 /* ipmi_errno set */
441 442 return (NULL);
442 443
443 444 /* RMCP header */
444 445 (void) memset(&rmcp_hdr, 0, sizeof (rmcp_hdr));
445 446 rmcp_hdr.rh_version = RMCP_VERSION_1;
446 447 rmcp_hdr.rh_msg_class = RMCP_CLASS_IPMI;
447 448 rmcp_hdr.rh_seq = 0xff;
448 449 (void) memcpy(msg, &rmcp_hdr, sizeof (rmcp_hdr));
449 450 off = sizeof (rmcp_hdr);
450 451
451 452 /* IPMI session header */
452 453 (void) memset(&session_hdr, 0, sizeof (session_hdr));
453 454 if (! ilp->il_send_authcode)
454 455 session_hdr.sh_authtype = 0x00;
455 456 else
456 457 /* hardcode passwd authentication */
457 458 session_hdr.sh_authtype = 0x04;
458 459
459 460 (void) memcpy(&session_hdr.sh_seq, &ilp->il_in_seq, sizeof (uint32_t));
460 461 (void) memcpy(&session_hdr.sh_id, &ilp->il_session_id,
461 462 sizeof (uint32_t));
462 463
463 464 (void) memcpy(msg + off, &session_hdr, sizeof (session_hdr));
464 465 off += sizeof (session_hdr);
465 466
466 467 /* IPMI session authcode */
467 468 if (ilp->il_send_authcode && ilp->il_authtype) {
468 469 (void) memcpy(msg + off, ilp->il_authcode, 16);
469 470 off += 16;
470 471 }
|
↓ open down ↓ |
437 lines elided |
↑ open up ↑ |
471 472
472 473 /* message length */
473 474 msg[off++] = req->ic_dlen + 7;
474 475 cs = off;
475 476
476 477 /* IPMI message header */
477 478 (void) memset(&msg_hdr, 0, sizeof (msg_hdr));
478 479 msg_hdr.imh_addr1 = IPMI_BMC_SLAVE_ADDR;
479 480 msg_hdr.imh_lun = req->ic_lun;
480 481 msg_hdr.imh_netfn = req->ic_netfn;
481 - tmp = off - cs;
482 - msg_hdr.imh_csum = ipmi_csum(msg + cs, tmp);
482 + msg_hdr.imh_csum = ipmi_csum((uint8_t *)&msg_hdr, sizeof (msg_hdr));
483 483 cs = off;
484 484 msg_hdr.imh_addr2 = IPMI_BMC_SLAVE_ADDR;
485 485 entry->ire_rq_seq = curr_seq++;
486 486 msg_hdr.imh_seq = entry->ire_rq_seq << 2;
487 487 msg_hdr.imh_cmd = req->ic_cmd;
488 488 (void) memcpy(msg + off, &msg_hdr, sizeof (msg_hdr));
489 489 off += sizeof (msg_hdr);
490 490
491 491 /* message data */
492 492 if (req->ic_dlen != 0) {
493 493 (void) memcpy(msg + off, req->ic_data, req->ic_dlen);
494 494 off += req->ic_dlen;
495 495 }
496 496
497 497 /* message data checksum */
498 498 tmp = off - cs;
499 499 msg[off++] = ipmi_csum(msg + cs, tmp);
500 500
501 501 if (ilp->il_in_seq) {
502 502 ilp->il_in_seq++;
503 503 if (ilp->il_in_seq == 0)
504 504 ilp->il_in_seq++;
505 505 }
506 506
507 507 entry->ire_msg_len = off;
508 508 entry->ire_msg_data = msg;
509 509
510 510 return (entry);
511 511 }
512 512
513 513 static int
514 514 ipmi_lan_send(void *data, ipmi_cmd_t *cmd, ipmi_cmd_t *response,
515 515 int *completion)
516 516 {
517 517 ipmi_lan_t *ilp = (ipmi_lan_t *)data;
518 518 ipmi_rq_entry_t *entry = NULL;
519 519 ipmi_rs_t *rsp = NULL;
520 520 uint_t try = 0;
521 521
522 522 for (;;) {
523 523 if ((entry = ipmi_lan_build_cmd(ilp->il_ihp, cmd)) == NULL)
524 524 return (-1);
525 525
526 526 if (ipmi_lan_send_packet(ilp->il_ihp, entry->ire_msg_data,
527 527 entry->ire_msg_len) < 0) {
528 528 if (++try >= ilp->il_num_retries)
529 529 return (-1);
530 530 (void) usleep(5000);
531 531 continue;
532 532 }
533 533
534 534 (void) usleep(100);
535 535
536 536 if ((rsp = ipmi_lan_poll_recv(ilp->il_ihp)) != NULL)
537 537 break;
538 538
539 539 (void) usleep(5000);
540 540 ipmi_req_remove_entry(ilp->il_ihp, entry->ire_rq_seq,
541 541 entry->ire_req.ic_cmd);
542 542
543 543 if (++try >= ilp->il_num_retries)
544 544 return (-1);
545 545 }
546 546 response->ic_netfn = rsp->ir_ihdr.imh_netfn;
547 547 response->ic_lun = rsp->ir_ihdr.imh_lun;
548 548 response->ic_cmd = rsp->ir_ihdr.imh_cmd;
549 549 if (rsp->ir_ccode != 0) {
550 550 *completion = rsp->ir_ccode;
551 551 response->ic_dlen = 0;
552 552 response->ic_data = NULL;
553 553 } else {
554 554 *completion = 0;
555 555 response->ic_dlen = rsp->ir_dlen;
556 556 response->ic_data = rsp->ir_data;
557 557 }
558 558 return (0);
559 559 }
560 560
561 561 /*
562 562 * IPMI Get Session Challenge Command
563 563 *
564 564 * Copies the returned session ID and 16-byte challenge string to the supplied
565 565 * buffers
566 566 *
567 567 * See section 22.16
568 568 */
569 569 static int
570 570 ipmi_get_session_challenge_cmd(ipmi_handle_t *ihp, uint32_t *session_id,
571 571 uint8_t *challenge)
572 572 {
573 573 ipmi_cmd_t cmd, resp;
574 574 ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata;
575 575 char msg_data[17];
576 576 int ccode;
577 577
578 578 (void) memset(msg_data, 0, 17);
579 579
580 580 switch (ilp->il_authtype) {
581 581 case IPMI_SESSION_AUTHTYPE_NONE:
582 582 msg_data[0] = 0x00;
583 583 break;
584 584 case IPMI_SESSION_AUTHTYPE_MD2:
585 585 msg_data[0] = 0x01;
586 586 break;
587 587 case IPMI_SESSION_AUTHTYPE_MD5:
588 588 msg_data[0] = 0x02;
589 589 break;
590 590 case IPMI_SESSION_AUTHTYPE_PASSWORD:
591 591 msg_data[0] = 0x04;
592 592 break;
593 593 case IPMI_SESSION_AUTHTYPE_OEM:
594 594 msg_data[0] = 0x05;
595 595 break;
596 596 }
597 597 (void) memcpy(msg_data + 1, ilp->il_user, 16);
598 598
599 599 cmd.ic_netfn = IPMI_NETFN_APP;
600 600 cmd.ic_lun = 0;
601 601 cmd.ic_cmd = IPMI_CMD_GET_SESSION_CHALLENGE;
602 602 cmd.ic_data = msg_data;
603 603 cmd.ic_dlen = 17;
604 604
605 605 if (ipmi_lan_send(ilp, &cmd, &resp, &ccode) != 0 || ccode)
606 606 return (ipmi_set_error(ihp, EIPMI_LAN_CHALLENGE, NULL));
607 607
608 608 (void) memcpy(session_id, resp.ic_data, 4);
609 609 (void) memcpy(challenge, (uint8_t *)resp.ic_data + 4, 16);
610 610
611 611 return (0);
612 612 }
613 613
614 614 /*
615 615 * IPMI Activate Session Command
616 616 *
617 617 * See section 22.17
618 618 */
619 619 static int
620 620 ipmi_activate_session_cmd(ipmi_handle_t *ihp)
621 621 {
622 622 ipmi_cmd_t cmd, resp;
623 623 ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata;
624 624 uint8_t msg_data[22], *resp_data;
625 625 int ccode;
626 626
627 627 cmd.ic_netfn = IPMI_NETFN_APP;
628 628 cmd.ic_lun = 0;
629 629 cmd.ic_cmd = IPMI_CMD_ACTIVATE_SESSION;
630 630
631 631 switch (ilp->il_authtype) {
632 632 case IPMI_SESSION_AUTHTYPE_NONE:
633 633 msg_data[0] = 0x00;
634 634 break;
635 635 case IPMI_SESSION_AUTHTYPE_MD2:
636 636 msg_data[0] = 0x01;
637 637 break;
638 638 case IPMI_SESSION_AUTHTYPE_MD5:
639 639 msg_data[0] = 0x02;
640 640 break;
641 641 case IPMI_SESSION_AUTHTYPE_PASSWORD:
642 642 msg_data[0] = 0x04;
643 643 break;
644 644 case IPMI_SESSION_AUTHTYPE_OEM:
645 645 msg_data[0] = 0x05;
646 646 break;
647 647 }
648 648 msg_data[1] = ilp->il_privlvl;
649 649
650 650 (void) memcpy(msg_data + 2, ilp->il_challenge, 16);
651 651
652 652 /* setup initial outbound sequence number */
653 653 (void) get_random(msg_data + 18, 4);
654 654
655 655 cmd.ic_data = msg_data;
656 656 cmd.ic_dlen = 22;
657 657
658 658 ilp->il_send_authcode = B_TRUE;
659 659
660 660 if (ipmi_lan_send(ilp, &cmd, &resp, &ccode) != 0 || ccode) {
661 661 ilp->il_send_authcode = B_FALSE;
662 662 return (ipmi_set_error(ihp, EIPMI_LAN_SESSION, NULL));
663 663 }
664 664
665 665 resp_data = (uint8_t *)resp.ic_data;
666 666 (void) memcpy(&ilp->il_session_id, resp_data + 1, 4);
667 667 ilp->il_in_seq = resp_data[8] << 24 | resp_data[7] << 16 |
668 668 resp_data[6] << 8 | resp_data[5];
669 669 if (ilp->il_in_seq == 0)
670 670 ++ilp->il_in_seq;
671 671
672 672 return (0);
673 673 }
674 674
675 675
676 676 /*
677 677 * See section 22.18
678 678 *
679 679 * returns privilege level or -1 on error
680 680 */
681 681 static int
682 682 ipmi_set_session_privlvl_cmd(ipmi_handle_t *ihp, uint8_t privlvl)
683 683 {
684 684 ipmi_cmd_t cmd, resp;
685 685 int ret = 0, ccode;
686 686
687 687 if (privlvl > IPMI_SESSION_PRIV_OEM)
688 688 return (ipmi_set_error(ihp, EIPMI_BADPARAM, NULL));
689 689
690 690 cmd.ic_netfn = IPMI_NETFN_APP;
691 691 cmd.ic_lun = 0;
692 692 cmd.ic_cmd = IPMI_CMD_SET_SESSION_PRIVLVL;
693 693 cmd.ic_data = &privlvl;
694 694 cmd.ic_dlen = 1;
695 695
696 696 if (ipmi_lan_send(ihp->ih_tdata, &cmd, &resp, &ccode) != 0)
697 697 ret = ipmi_set_error(ihp, EIPMI_LAN_SETPRIV, NULL);
698 698
699 699 return (ret);
700 700 }
701 701
702 702 /*
703 703 * See section 22.19
704 704 */
705 705 static int
706 706 ipmi_close_session_cmd(ipmi_handle_t *ihp)
707 707 {
708 708 ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata;
709 709 ipmi_cmd_t cmd, resp;
710 710 uint8_t msg_data[4];
711 711 int ret = 0, ccode;
712 712
713 713 if (! ilp->il_session_active)
714 714 return (-1);
715 715
716 716 (void) memcpy(&msg_data, &ilp->il_session_id, 4);
717 717
718 718 cmd.ic_netfn = IPMI_NETFN_APP;
719 719 cmd.ic_lun = 0;
720 720 cmd.ic_cmd = IPMI_CMD_CLOSE_SESSION;
721 721 cmd.ic_data = msg_data;
722 722 cmd.ic_dlen = 4;
723 723
724 724 if (ipmi_lan_send(ilp, &cmd, &resp, &ccode) != 0)
725 725 ret = -1;
726 726
727 727 return (ret);
728 728 }
729 729
730 730 /*
731 731 * IPMI LAN Session Activation
732 732 *
733 733 * See section 13.14
734 734 *
735 735 * 1. send "RMCP Presence Ping" message, response message will
736 736 * indicate whether the platform supports IPMI
737 737 * 2. send "Get Channel Authentication Capabilities" command
738 738 * with AUTHTYPE = none, response packet will contain information
739 739 * about supported challenge/response authentication types
740 740 * 3. send "Get Session Challenge" command with AUTHTYPE = none
741 741 * and indicate the authentication type in the message, response
742 742 * packet will contain challenge string and temporary session ID.
743 743 * 4. send "Activate Session" command, authenticated with AUTHTYPE
744 744 * sent in previous message. Also sends the initial value for
745 745 * the outbound sequence number for BMC.
746 746 * 5. BMC returns response confirming session activation and
747 747 * session ID for this session and initial inbound sequence.
748 748 */
749 749 static int
750 750 ipmi_lan_activate_session(ipmi_handle_t *ihp)
751 751 {
752 752 ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata;
753 753 ipmi_channel_auth_caps_t *ac;
754 754
755 755 if (ipmi_lan_ping(ihp) != 0)
756 756 return (-1);
757 757
758 758 if ((ac = ipmi_get_channel_auth_caps(ihp, IPMI_LAN_CHANNEL_E,
759 759 ilp->il_privlvl)) == NULL)
760 760 return (-1);
761 761
762 762 /*
763 763 * For the sake of simplicity, we're just supporting basic password
764 764 * authentication. If this authentication type is not supported then
765 765 * we'll bail here.
766 766 */
767 767 if (!(ac->cap_authtype & IPMI_SESSION_AUTHTYPE_PASSWORD)) {
768 768 free(ac);
769 769 return (ipmi_set_error(ihp, EIPMI_LAN_PASSWD_NOTSUP, NULL));
770 770 }
771 771 free(ac);
772 772
773 773 if (ipmi_get_session_challenge_cmd(ihp, &ilp->il_session_id,
774 774 ilp->il_challenge) != 0)
775 775 return (-1);
776 776
777 777 if (ipmi_activate_session_cmd(ihp) != 0)
778 778 return (-1);
779 779
780 780 ilp->il_session_active = B_TRUE;
781 781
782 782 if (ipmi_set_session_privlvl_cmd(ihp, ilp->il_privlvl) != 0)
783 783 return (-1);
784 784
785 785 return (0);
786 786 }
787 787
788 788 static void
789 789 ipmi_lan_close(void *data)
790 790 {
791 791 ipmi_lan_t *ilp = (ipmi_lan_t *)data;
792 792
793 793 if (ilp->il_session_active)
794 794 (void) ipmi_close_session_cmd(ilp->il_ihp);
795 795
796 796 if (ilp->il_sd >= 0)
797 797 (void) close(ilp->il_sd);
798 798
799 799 ipmi_req_clear_entries(ilp->il_ihp);
800 800 ipmi_free(ilp->il_ihp, ipmi_req_entries);
801 801 ipmi_free(ilp->il_ihp, ilp);
802 802 }
803 803
804 804 static void *
805 805 ipmi_lan_open(ipmi_handle_t *ihp, nvlist_t *params)
806 806 {
807 807 int rc;
808 808 struct hostent *host;
809 809 ipmi_lan_t *ilp;
810 810 char *hostname, *user, *authcode;
811 811
812 812 if ((ilp = ipmi_zalloc(ihp, sizeof (ipmi_lan_t))) == NULL) {
813 813 /* ipmi errno set */
814 814 return (NULL);
815 815 }
816 816 ilp->il_ihp = ihp;
817 817 ihp->ih_tdata = ilp;
818 818
819 819 /*
820 820 * Parse the parameters passed in the params nvlist. The following
821 821 * parameters are required
822 822 * IPMI_LAN_HOST, IPMI_LAN_USER and IPMI_LAN_PASSWD
823 823 *
824 824 * If any of these were not specified then we abort
825 825 */
826 826 if (nvlist_lookup_string(params, IPMI_LAN_HOST, &hostname) ||
827 827 nvlist_lookup_string(params, IPMI_LAN_USER, &user) ||
828 828 nvlist_lookup_string(params, IPMI_LAN_PASSWD, &authcode)) {
829 829 ipmi_free(ihp, ilp);
830 830 (void) ipmi_set_error(ihp, EIPMI_BADPARAM, NULL);
831 831 return (NULL);
832 832 }
833 833 (void) strncpy(ilp->il_host, hostname, MAXHOSTNAMELEN);
834 834 (void) strncpy(ilp->il_user, user, 16);
835 835 (void) strncpy(ilp->il_authcode, authcode, 16);
836 836
837 837 /*
838 838 * IPMI_LAN_PORT is an optional parameter and defaults to port 623
839 839 * IPMI_LAN_PRIVLVL is also optional and defaults to admin
840 840 * IPMI_LAN_TIMEOUT is optional and will default to 3 seconds
841 841 * IPMI_LAN_NUM_RETIES is optional and will default to 5
842 842 */
843 843 if (nvlist_lookup_uint16(params, IPMI_LAN_PORT, &ilp->il_port))
844 844 ilp->il_port = RMCP_UDP_PORT;
845 845
846 846 if (nvlist_lookup_uint8(params, IPMI_LAN_PRIVLVL, &ilp->il_privlvl))
847 847 ilp->il_privlvl = IPMI_SESSION_PRIV_ADMIN;
848 848
849 849 if (nvlist_lookup_uint32(params, IPMI_LAN_TIMEOUT, &ilp->il_timeout))
850 850 ilp->il_timeout = DEF_IPMI_LAN_TIMEOUT;
851 851
852 852 if (nvlist_lookup_uint8(params, IPMI_LAN_NUM_RETRIES,
853 853 &ilp->il_num_retries))
854 854 ilp->il_num_retries = DEF_IPMI_LAN_NUM_RETRIES;
855 855
856 856 ilp->il_authtype = IPMI_SESSION_AUTHTYPE_PASSWORD;
857 857
858 858 /*
859 859 * Open up and connect a UDP socket between us and the service
860 860 * processor
861 861 */
862 862 ilp->il_addr.sin_family = AF_INET;
863 863 ilp->il_addr.sin_port = htons(ilp->il_port);
864 864
865 865 rc = inet_pton(AF_INET, (const char *)ilp->il_host,
866 866 &ilp->il_addr.sin_addr);
867 867 if (rc <= 0) {
868 868 if ((host = gethostbyname((const char *)ilp->il_host))
869 869 == NULL) {
870 870 ipmi_free(ihp, ilp);
871 871 (void) ipmi_set_error(ihp, EIPMI_LAN_OPEN_FAILED, NULL);
872 872 return (NULL);
873 873 }
874 874 ilp->il_addr.sin_family = host->h_addrtype;
875 875 (void) memcpy(&ilp->il_addr.sin_addr, host->h_addr,
876 876 host->h_length);
877 877 }
878 878
879 879 if ((ilp->il_sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
880 880 ipmi_free(ihp, ilp);
881 881 (void) ipmi_set_error(ihp, EIPMI_LAN_OPEN_FAILED, NULL);
882 882 return (NULL);
883 883 }
884 884 if (connect(ilp->il_sd, (struct sockaddr *)&ilp->il_addr,
885 885 sizeof (struct sockaddr_in)) < 0) {
886 886 ipmi_lan_close(ilp);
887 887 (void) ipmi_set_error(ihp, EIPMI_LAN_OPEN_FAILED, NULL);
888 888 return (NULL);
889 889 }
890 890
891 891 if ((ipmi_req_entries = ipmi_zalloc(ihp, sizeof (ipmi_rq_entry_t)))
892 892 == NULL)
893 893 return (NULL);
894 894
895 895 /*
896 896 * Finally we start up the IPMI LAN session
897 897 */
898 898 if ((rc = ipmi_lan_activate_session(ihp)) < 0) {
899 899 ipmi_lan_close(ilp);
900 900 return (NULL);
901 901 }
902 902
903 903 return (ilp);
904 904 }
905 905
906 906 ipmi_transport_t ipmi_transport_lan = {
907 907 ipmi_lan_open,
908 908 ipmi_lan_close,
909 909 ipmi_lan_send
910 910 };
|
↓ open down ↓ |
418 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX