1 /* 2 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * Redistribution of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * Redistribution in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * Neither the name of Sun Microsystems, Inc. or the names of 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * This software is provided "AS IS," without a warranty of any kind. 20 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, 21 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A 22 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. 23 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE 24 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING 25 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL 26 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, 27 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR 28 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF 29 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, 30 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 31 */ 32 33 #include <stdlib.h> 34 #include <stdio.h> 35 #include <string.h> 36 #include <strings.h> 37 #include <sys/types.h> 38 #include <sys/socket.h> 39 #include <netinet/in.h> 40 #include <arpa/inet.h> 41 #include <errno.h> 42 #include <unistd.h> 43 #include <signal.h> 44 #include <setjmp.h> 45 #include <netdb.h> 46 #include <limits.h> 47 48 #include <ipmitool/ipmi.h> 49 #include <ipmitool/log.h> 50 #include <ipmitool/ipmi_intf.h> 51 #include <ipmitool/helper.h> 52 #include <ipmitool/ipmi_constants.h> 53 #include <ipmitool/ipmi_strings.h> 54 #include <ipmitool/ipmi_lanp.h> 55 #include <ipmitool/ipmi_channel.h> 56 #include <ipmitool/ipmi_user.h> 57 58 extern int verbose; 59 60 static void print_lan_alert_print_usage(void); 61 static void print_lan_alert_set_usage(void); 62 static void print_lan_set_usage(void); 63 static void print_lan_set_access_usage(void); 64 static void print_lan_set_arp_usage(void); 65 static void print_lan_set_auth_usage(void); 66 static void print_lan_set_bakgw_usage(void); 67 static void print_lan_set_cipher_privs_usage(void); 68 static void print_lan_set_defgw_usage(void); 69 static void print_lan_set_ipsrc_usage(void); 70 static void print_lan_set_snmp_usage(void); 71 static void print_lan_set_vlan_usage(void); 72 static void print_lan_usage(void); 73 74 /* is_lan_channel - Check if channel is LAN medium 75 * 76 * return 1 if channel is LAN 77 * return 0 if channel is not LAN 78 * 79 * @intf: ipmi interface handle 80 * @chan: channel number to check 81 */ 82 static int 83 is_lan_channel(struct ipmi_intf * intf, uint8_t chan) 84 { 85 uint8_t medium; 86 87 if (chan < 1 || chan > IPMI_CHANNEL_NUMBER_MAX) 88 return 0; 89 90 medium = ipmi_get_channel_medium(intf, chan); 91 92 if (medium == IPMI_CHANNEL_MEDIUM_LAN || 93 medium == IPMI_CHANNEL_MEDIUM_LAN_OTHER) 94 return 1; 95 96 return 0; 97 } 98 99 /* find_lan_channel - Find first channel that is LAN 100 * 101 * return channel number if successful 102 * return 0 if no lan channel found, which is not a valid LAN channel 103 * 104 * @intf: ipmi interface handle 105 * @start: channel number to start searching from 106 */ 107 static uint8_t 108 find_lan_channel(struct ipmi_intf * intf, uint8_t start) 109 { 110 uint8_t chan = 0; 111 112 for (chan = start; chan < IPMI_CHANNEL_NUMBER_MAX; chan++) { 113 if (is_lan_channel(intf, chan)) { 114 return chan; 115 } 116 } 117 return 0; 118 } 119 120 /* get_lan_param_select - Query BMC for LAN parameter data 121 * 122 * return pointer to lan_param if successful 123 * if parameter not supported then 124 * return pointer to lan_param with 125 * lan_param->data == NULL and lan_param->data_len == 0 126 * return NULL on error 127 * 128 * @intf: ipmi interface handle 129 * @chan: ipmi channel 130 * @param: lan parameter id 131 * @select: lan parameter set selector 132 */ 133 static struct lan_param * 134 get_lan_param_select(struct ipmi_intf * intf, uint8_t chan, int param, int select) 135 { 136 struct lan_param * p = NULL; 137 struct ipmi_rs * rsp; 138 struct ipmi_rq req; 139 int i = 0; 140 uint8_t msg_data[4]; 141 142 for (i = 0; ipmi_lan_params[i].cmd != (-1); i++) { 143 if (ipmi_lan_params[i].cmd == param) { 144 p = &ipmi_lan_params[i]; 145 break; 146 } 147 } 148 149 if (p == NULL) { 150 lprintf(LOG_INFO, "Get LAN Parameter failed: Unknown parameter."); 151 return NULL; 152 } 153 154 msg_data[0] = chan; 155 msg_data[1] = p->cmd; 156 msg_data[2] = select; 157 msg_data[3] = 0; 158 159 memset(&req, 0, sizeof(req)); 160 req.msg.netfn = IPMI_NETFN_TRANSPORT; 161 req.msg.cmd = IPMI_LAN_GET_CONFIG; 162 req.msg.data = msg_data; 163 req.msg.data_len = 4; 164 165 rsp = intf->sendrecv(intf, &req); 166 if (rsp == NULL) { 167 lprintf(LOG_INFO, "Get LAN Parameter '%s' command failed", p->desc); 168 return NULL; 169 } 170 171 switch (rsp->ccode) 172 { 173 case 0x00: /* successful */ 174 break; 175 176 case 0x80: /* parameter not supported */ 177 case 0xc9: /* parameter out of range */ 178 case 0xcc: /* invalid data field in request */ 179 180 /* these completion codes usually mean parameter not supported */ 181 lprintf(LOG_INFO, "Get LAN Parameter '%s' command failed: %s", 182 p->desc, val2str(rsp->ccode, completion_code_vals)); 183 p->data = NULL; 184 p->data_len = 0; 185 return p; 186 187 default: 188 189 /* other completion codes are treated as error */ 190 lprintf(LOG_INFO, "Get LAN Parameter '%s' command failed: %s", 191 p->desc, val2str(rsp->ccode, completion_code_vals)); 192 return NULL; 193 } 194 195 p->data = rsp->data + 1; 196 p->data_len = rsp->data_len - 1; 197 198 return p; 199 } 200 201 /* get_lan_param - Query BMC for LAN parameter data 202 * 203 * return pointer to lan_param if successful 204 * if parameter not supported then 205 * return pointer to lan_param with 206 * lan_param->data == NULL and lan_param->data_len == 0 207 * return NULL on error 208 * 209 * @intf: ipmi interface handle 210 * @chan: ipmi channel 211 * @param: lan parameter id 212 */ 213 static struct lan_param * 214 get_lan_param(struct ipmi_intf * intf, uint8_t chan, int param) 215 { 216 return get_lan_param_select(intf, chan, param, 0); 217 } 218 219 /* set_lan_param_wait - Wait for Set LAN Parameter command to complete 220 * 221 * On some systems this can take unusually long so we wait for the write 222 * to take effect and verify that the data was written successfully 223 * before continuing or retrying. 224 * 225 * returns 0 on success 226 * returns -1 on error 227 * 228 * @intf: ipmi interface handle 229 * @chan: ipmi channel 230 * @param: lan parameter id 231 * @data: lan parameter data 232 * @len: length of lan parameter data 233 */ 234 static int 235 set_lan_param_wait(struct ipmi_intf * intf, uint8_t chan, 236 int param, uint8_t * data, int len) 237 { 238 struct lan_param * p; 239 int retry = 10; /* 10 retries */ 240 241 lprintf(LOG_DEBUG, "Waiting for Set LAN Parameter to complete..."); 242 if (verbose > 1) 243 printbuf(data, len, "SET DATA"); 244 245 for (;;) { 246 p = get_lan_param(intf, chan, param); 247 if (p == NULL) { 248 sleep(IPMI_LANP_TIMEOUT); 249 if (retry-- == 0) 250 return -1; 251 continue; 252 } 253 if (verbose > 1) 254 printbuf(p->data, p->data_len, "READ DATA"); 255 if (p->data_len != len) { 256 sleep(IPMI_LANP_TIMEOUT); 257 if (retry-- == 0) { 258 lprintf(LOG_WARNING, "Mismatched data lengths: %d != %d", 259 p->data_len, len); 260 return -1; 261 } 262 continue; 263 } 264 if (memcmp(data, p->data, len) != 0) { 265 sleep(IPMI_LANP_TIMEOUT); 266 if (retry-- == 0) { 267 lprintf(LOG_WARNING, "LAN Parameter Data does not match! " 268 "Write may have failed."); 269 return -1; 270 } 271 continue; 272 } 273 break; 274 } 275 return 0; 276 } 277 278 /* __set_lan_param - Write LAN Parameter data to BMC 279 * 280 * This function does the actual work of writing the LAN parameter 281 * to the BMC and calls set_lan_param_wait() if requested. 282 * 283 * returns 0 on success 284 * returns -1 on error 285 * 286 * @intf: ipmi interface handle 287 * @chan: ipmi channel 288 * @param: lan parameter id 289 * @data: lan parameter data 290 * @len: length of lan parameter data 291 * @wait: whether to wait for write completion 292 */ 293 static int 294 __set_lan_param(struct ipmi_intf * intf, uint8_t chan, 295 int param, uint8_t * data, int len, int wait) 296 { 297 struct ipmi_rs * rsp; 298 struct ipmi_rq req; 299 uint8_t msg_data[32]; 300 301 if (param < 0) 302 return -1; 303 304 msg_data[0] = chan; 305 msg_data[1] = param; 306 307 memcpy(&msg_data[2], data, len); 308 memset(&req, 0, sizeof(req)); 309 req.msg.netfn = IPMI_NETFN_TRANSPORT; 310 req.msg.cmd = IPMI_LAN_SET_CONFIG; 311 req.msg.data = msg_data; 312 req.msg.data_len = len+2; 313 314 rsp = intf->sendrecv(intf, &req); 315 if (rsp == NULL) { 316 lprintf(LOG_ERR, "Set LAN Parameter failed"); 317 return -1; 318 } 319 if ((rsp->ccode > 0) && (wait != 0)) { 320 lprintf(LOG_DEBUG, "Warning: Set LAN Parameter failed: %s", 321 val2str(rsp->ccode, completion_code_vals)); 322 if (rsp->ccode == 0xcc) { 323 /* retry hack for invalid data field ccode */ 324 int retry = 10; /* 10 retries */ 325 lprintf(LOG_DEBUG, "Retrying..."); 326 for (;;) { 327 if (retry-- == 0) 328 break; 329 sleep(IPMI_LANP_TIMEOUT); 330 rsp = intf->sendrecv(intf, &req); 331 if (rsp == NULL) 332 continue; 333 if (rsp->ccode > 0) 334 continue; 335 return set_lan_param_wait(intf, chan, param, data, len); 336 } 337 } 338 else if (rsp->ccode != 0xff) { 339 /* let 0xff ccode continue */ 340 return -1; 341 } 342 } 343 344 if (wait == 0) 345 return 0; 346 return set_lan_param_wait(intf, chan, param, data, len); 347 } 348 349 /* ipmi_lanp_lock_state - Retrieve set-in-progress status 350 * 351 * returns one of: 352 * IPMI_LANP_WRITE_UNLOCK 353 * IPMI_LANP_WRITE_LOCK 354 * IPMI_LANP_WRITE_COMMIT 355 * -1 on error/if not supported 356 * 357 * @intf: ipmi interface handle 358 * @chan: ipmi channel 359 */ 360 static int 361 ipmi_lanp_lock_state(struct ipmi_intf * intf, uint8_t chan) 362 { 363 struct lan_param * p; 364 p = get_lan_param(intf, chan, IPMI_LANP_SET_IN_PROGRESS); 365 if (p == NULL) 366 return -1; 367 if (p->data == NULL) 368 return -1; 369 return (p->data[0] & 3); 370 } 371 372 /* ipmi_lanp_lock - Lock set-in-progress bits for our use 373 * 374 * Write to the Set-In-Progress LAN parameter to indicate 375 * to other management software that we are modifying parameters. 376 * 377 * No meaningful return value because this is an optional 378 * requirement in IPMI spec and not found on many BMCs. 379 * 380 * @intf: ipmi interface handle 381 * @chan: ipmi channel 382 */ 383 static void 384 ipmi_lanp_lock(struct ipmi_intf * intf, uint8_t chan) 385 { 386 uint8_t val = IPMI_LANP_WRITE_LOCK; 387 int retry = 3; 388 389 for (;;) { 390 int state = ipmi_lanp_lock_state(intf, chan); 391 if (state == -1) 392 break; 393 if (state == val) 394 break; 395 if (retry-- == 0) 396 break; 397 __set_lan_param(intf, chan, IPMI_LANP_SET_IN_PROGRESS, 398 &val, 1, 0); 399 } 400 } 401 402 /* ipmi_lanp_unlock - Unlock set-in-progress bits 403 * 404 * Write to the Set-In-Progress LAN parameter, first with 405 * a "commit" instruction and then unlocking it. 406 * 407 * No meaningful return value because this is an optional 408 * requirement in IPMI spec and not found on many BMCs. 409 * 410 * @intf: ipmi interface handle 411 * @chan: ipmi channel 412 */ 413 static void 414 ipmi_lanp_unlock(struct ipmi_intf * intf, uint8_t chan) 415 { 416 uint8_t val = IPMI_LANP_WRITE_COMMIT; 417 int rc; 418 419 rc = __set_lan_param(intf, chan, IPMI_LANP_SET_IN_PROGRESS, &val, 1, 0); 420 if (rc < 0) { 421 lprintf(LOG_DEBUG, "LAN Parameter Commit not supported"); 422 } 423 424 val = IPMI_LANP_WRITE_UNLOCK; 425 __set_lan_param(intf, chan, IPMI_LANP_SET_IN_PROGRESS, &val, 1, 0); 426 } 427 428 /* set_lan_param - Wrap LAN parameter write with set-in-progress lock 429 * 430 * Returns value from __set_lan_param() 431 * 432 * @intf: ipmi interface handle 433 * @chan: ipmi channel 434 * @param: lan parameter id 435 * @data: lan parameter data 436 * @len: length of lan parameter data 437 */ 438 static int 439 set_lan_param(struct ipmi_intf * intf, uint8_t chan, 440 int param, uint8_t * data, int len) 441 { 442 int rc; 443 ipmi_lanp_lock(intf, chan); 444 rc = __set_lan_param(intf, chan, param, data, len, 1); 445 ipmi_lanp_unlock(intf, chan); 446 return rc; 447 } 448 449 /* set_lan_param_nowait - Wrap LAN parameter write without set-in-progress lock 450 * 451 * Returns value from __set_lan_param() 452 * 453 * @intf: ipmi interface handle 454 * @chan: ipmi channel 455 * @param: lan parameter id 456 * @data: lan parameter data 457 * @len: length of lan parameter data 458 */ 459 static int 460 set_lan_param_nowait(struct ipmi_intf * intf, uint8_t chan, 461 int param, uint8_t * data, int len) 462 { 463 int rc; 464 ipmi_lanp_lock(intf, chan); 465 rc = __set_lan_param(intf, chan, param, data, len, 0); 466 ipmi_lanp_unlock(intf, chan); 467 return rc; 468 } 469 470 static int 471 lan_set_arp_interval(struct ipmi_intf * intf, uint8_t chan, uint8_t ival) 472 { 473 struct lan_param *lp; 474 uint8_t interval = 0; 475 int rc = 0; 476 477 lp = get_lan_param(intf, chan, IPMI_LANP_GRAT_ARP); 478 if (lp == NULL) 479 return -1; 480 if (lp->data == NULL) 481 return -1; 482 483 if (ival != 0) { 484 if (((UINT8_MAX - 1) / 2) < ival) { 485 lprintf(LOG_ERR, "Given ARP interval '%u' is too big.", ival); 486 return (-1); 487 } 488 interval = (ival * 2) - 1; 489 rc = set_lan_param(intf, chan, IPMI_LANP_GRAT_ARP, &interval, 1); 490 } else { 491 interval = lp->data[0]; 492 } 493 494 printf("BMC-generated Gratuitous ARP interval: %.1f seconds\n", 495 (float)((interval + 1) / 2)); 496 497 return rc; 498 } 499 500 static int 501 lan_set_arp_generate(struct ipmi_intf * intf, 502 uint8_t chan, uint8_t ctl) 503 { 504 struct lan_param *lp; 505 uint8_t data; 506 507 lp = get_lan_param(intf, chan, IPMI_LANP_BMC_ARP); 508 if (lp == NULL) 509 return -1; 510 if (lp->data == NULL) 511 return -1; 512 data = lp->data[0]; 513 514 /* set arp generate bitflag */ 515 if (ctl == 0) 516 data &= ~0x1; 517 else 518 data |= 0x1; 519 520 printf("%sabling BMC-generated Gratuitous ARPs\n", ctl ? "En" : "Dis"); 521 return set_lan_param(intf, chan, IPMI_LANP_BMC_ARP, &data, 1); 522 } 523 524 static int 525 lan_set_arp_respond(struct ipmi_intf * intf, 526 uint8_t chan, uint8_t ctl) 527 { 528 struct lan_param *lp; 529 uint8_t data; 530 531 lp = get_lan_param(intf, chan, IPMI_LANP_BMC_ARP); 532 if (lp == NULL) 533 return -1; 534 if (lp->data == NULL) 535 return -1; 536 data = lp->data[0]; 537 538 /* set arp response bitflag */ 539 if (ctl == 0) 540 data &= ~0x2; 541 else 542 data |= 0x2; 543 544 printf("%sabling BMC-generated ARP responses\n", ctl ? "En" : "Dis"); 545 return set_lan_param(intf, chan, IPMI_LANP_BMC_ARP, &data, 1); 546 } 547 548 /* TODO - probably move elsewhere */ 549 static char priv_level_to_char(unsigned char priv_level) 550 { 551 char ret = 'X'; 552 553 switch (priv_level) 554 { 555 case IPMI_SESSION_PRIV_CALLBACK: 556 ret = 'c'; 557 break; 558 case IPMI_SESSION_PRIV_USER: 559 ret = 'u'; 560 break; 561 case IPMI_SESSION_PRIV_OPERATOR: 562 ret = 'o'; 563 break; 564 case IPMI_SESSION_PRIV_ADMIN: 565 ret = 'a'; 566 break; 567 case IPMI_SESSION_PRIV_OEM: 568 ret = 'O'; 569 break; 570 } 571 572 return ret; 573 } 574 575 576 static int 577 ipmi_lan_print(struct ipmi_intf * intf, uint8_t chan) 578 { 579 struct lan_param * p; 580 581 if (chan < 1 || chan > IPMI_CHANNEL_NUMBER_MAX) { 582 lprintf(LOG_ERR, "Invalid Channel %d", chan); 583 return -1; 584 } 585 586 /* find type of channel and only accept 802.3 LAN */ 587 if (!is_lan_channel(intf, chan)) { 588 lprintf(LOG_ERR, "Channel %d is not a LAN channel", chan); 589 return -1; 590 } 591 592 p = get_lan_param(intf, chan, IPMI_LANP_SET_IN_PROGRESS); 593 if (p == NULL) 594 return -1; 595 if (p->data != NULL) { 596 printf("%-24s: ", p->desc); 597 p->data[0] &= 3; 598 switch (p->data[0]) { 599 case 0: 600 printf("Set Complete\n"); 601 break; 602 case 1: 603 printf("Set In Progress\n"); 604 break; 605 case 2: 606 printf("Commit Write\n"); 607 break; 608 case 3: 609 printf("Reserved\n"); 610 break; 611 default: 612 printf("Unknown\n"); 613 } 614 } 615 616 p = get_lan_param(intf, chan, IPMI_LANP_AUTH_TYPE); 617 if (p == NULL) 618 return -1; 619 if (p->data != NULL) { 620 printf("%-24s: %s%s%s%s%s\n", p->desc, 621 (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_NONE) ? "NONE " : "", 622 (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_MD2) ? "MD2 " : "", 623 (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_MD5) ? "MD5 " : "", 624 (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD) ? "PASSWORD " : "", 625 (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_OEM) ? "OEM " : ""); 626 } 627 628 p = get_lan_param(intf, chan, IPMI_LANP_AUTH_TYPE_ENABLE); 629 if (p == NULL) 630 return -1; 631 if (p->data != NULL) { 632 printf("%-24s: Callback : %s%s%s%s%s\n", p->desc, 633 (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_NONE) ? "NONE " : "", 634 (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_MD2) ? "MD2 " : "", 635 (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_MD5) ? "MD5 " : "", 636 (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD) ? "PASSWORD " : "", 637 (p->data[0] & 1<<IPMI_SESSION_AUTHTYPE_OEM) ? "OEM " : ""); 638 printf("%-24s: User : %s%s%s%s%s\n", "", 639 (p->data[1] & 1<<IPMI_SESSION_AUTHTYPE_NONE) ? "NONE " : "", 640 (p->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD2) ? "MD2 " : "", 641 (p->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD5) ? "MD5 " : "", 642 (p->data[1] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD) ? "PASSWORD " : "", 643 (p->data[1] & 1<<IPMI_SESSION_AUTHTYPE_OEM) ? "OEM " : ""); 644 printf("%-24s: Operator : %s%s%s%s%s\n", "", 645 (p->data[2] & 1<<IPMI_SESSION_AUTHTYPE_NONE) ? "NONE " : "", 646 (p->data[2] & 1<<IPMI_SESSION_AUTHTYPE_MD2) ? "MD2 " : "", 647 (p->data[2] & 1<<IPMI_SESSION_AUTHTYPE_MD5) ? "MD5 " : "", 648 (p->data[2] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD) ? "PASSWORD " : "", 649 (p->data[2] & 1<<IPMI_SESSION_AUTHTYPE_OEM) ? "OEM " : ""); 650 printf("%-24s: Admin : %s%s%s%s%s\n", "", 651 (p->data[3] & 1<<IPMI_SESSION_AUTHTYPE_NONE) ? "NONE " : "", 652 (p->data[3] & 1<<IPMI_SESSION_AUTHTYPE_MD2) ? "MD2 " : "", 653 (p->data[3] & 1<<IPMI_SESSION_AUTHTYPE_MD5) ? "MD5 " : "", 654 (p->data[3] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD) ? "PASSWORD " : "", 655 (p->data[3] & 1<<IPMI_SESSION_AUTHTYPE_OEM) ? "OEM " : ""); 656 printf("%-24s: OEM : %s%s%s%s%s\n", "", 657 (p->data[4] & 1<<IPMI_SESSION_AUTHTYPE_NONE) ? "NONE " : "", 658 (p->data[4] & 1<<IPMI_SESSION_AUTHTYPE_MD2) ? "MD2 " : "", 659 (p->data[4] & 1<<IPMI_SESSION_AUTHTYPE_MD5) ? "MD5 " : "", 660 (p->data[4] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD) ? "PASSWORD " : "", 661 (p->data[4] & 1<<IPMI_SESSION_AUTHTYPE_OEM) ? "OEM " : ""); 662 } 663 664 p = get_lan_param(intf, chan, IPMI_LANP_IP_ADDR_SRC); 665 if (p == NULL) 666 return -1; 667 if (p->data != NULL) { 668 printf("%-24s: ", p->desc); 669 p->data[0] &= 0xf; 670 switch (p->data[0]) { 671 case 0: 672 printf("Unspecified\n"); 673 break; 674 case 1: 675 printf("Static Address\n"); 676 break; 677 case 2: 678 printf("DHCP Address\n"); 679 break; 680 case 3: 681 printf("BIOS Assigned Address\n"); 682 break; 683 default: 684 printf("Other\n"); 685 break; 686 } 687 } 688 689 p = get_lan_param(intf, chan, IPMI_LANP_IP_ADDR); 690 if (p == NULL) 691 return -1; 692 if (p->data != NULL) 693 printf("%-24s: %d.%d.%d.%d\n", p->desc, 694 p->data[0], p->data[1], p->data[2], p->data[3]); 695 696 p = get_lan_param(intf, chan, IPMI_LANP_SUBNET_MASK); 697 if (p == NULL) 698 return -1; 699 if (p->data != NULL) 700 printf("%-24s: %d.%d.%d.%d\n", p->desc, 701 p->data[0], p->data[1], p->data[2], p->data[3]); 702 703 p = get_lan_param(intf, chan, IPMI_LANP_MAC_ADDR); 704 if (p == NULL) 705 return -1; 706 if (p->data != NULL) 707 printf("%-24s: %02x:%02x:%02x:%02x:%02x:%02x\n", p->desc, 708 p->data[0], p->data[1], p->data[2], p->data[3], p->data[4], p->data[5]); 709 710 p = get_lan_param(intf, chan, IPMI_LANP_SNMP_STRING); 711 if (p == NULL) 712 return -1; 713 if (p->data != NULL) 714 printf("%-24s: %s\n", p->desc, p->data); 715 716 p = get_lan_param(intf, chan, IPMI_LANP_IP_HEADER); 717 if (p == NULL) 718 return -1; 719 if (p->data != NULL) 720 printf("%-24s: TTL=0x%02x Flags=0x%02x Precedence=0x%02x TOS=0x%02x\n", 721 p->desc, p->data[0], p->data[1] & 0xe0, p->data[2] & 0xe0, p->data[2] & 0x1e); 722 723 p = get_lan_param(intf, chan, IPMI_LANP_BMC_ARP); 724 if (p == NULL) 725 return -1; 726 if (p->data != NULL) 727 printf("%-24s: ARP Responses %sabled, Gratuitous ARP %sabled\n", p->desc, 728 (p->data[0] & 2) ? "En" : "Dis", (p->data[0] & 1) ? "En" : "Dis"); 729 730 p = get_lan_param(intf, chan, IPMI_LANP_GRAT_ARP); 731 if (p == NULL) 732 return -1; 733 if (p->data != NULL) 734 printf("%-24s: %.1f seconds\n", p->desc, (float)((p->data[0] + 1) / 2)); 735 736 p = get_lan_param(intf, chan, IPMI_LANP_DEF_GATEWAY_IP); 737 if (p == NULL) 738 return -1; 739 if (p->data != NULL) 740 printf("%-24s: %d.%d.%d.%d\n", p->desc, 741 p->data[0], p->data[1], p->data[2], p->data[3]); 742 743 p = get_lan_param(intf, chan, IPMI_LANP_DEF_GATEWAY_MAC); 744 if (p == NULL) 745 return -1; 746 if (p->data != NULL) 747 printf("%-24s: %02x:%02x:%02x:%02x:%02x:%02x\n", p->desc, 748 p->data[0], p->data[1], p->data[2], p->data[3], p->data[4], p->data[5]); 749 750 p = get_lan_param(intf, chan, IPMI_LANP_BAK_GATEWAY_IP); 751 if (p == NULL) 752 return -1; 753 if (p->data != NULL) 754 printf("%-24s: %d.%d.%d.%d\n", p->desc, 755 p->data[0], p->data[1], p->data[2], p->data[3]); 756 757 p = get_lan_param(intf, chan, IPMI_LANP_BAK_GATEWAY_MAC); 758 if (p == NULL) 759 return -1; 760 if (p->data != NULL) 761 printf("%-24s: %02x:%02x:%02x:%02x:%02x:%02x\n", p->desc, 762 p->data[0], p->data[1], p->data[2], p->data[3], p->data[4], p->data[5]); 763 764 p = get_lan_param(intf, chan, IPMI_LANP_VLAN_ID); 765 if (p != NULL && p->data != NULL) { 766 int id = ((p->data[1] & 0x0f) << 8) + p->data[0]; 767 if (p->data[1] & 0x80) 768 printf("%-24s: %d\n", p->desc, id); 769 else 770 printf("%-24s: Disabled\n", p->desc); 771 } 772 773 p = get_lan_param(intf, chan, IPMI_LANP_VLAN_PRIORITY); 774 if (p != NULL && p->data != NULL) 775 printf("%-24s: %d\n", p->desc, p->data[0] & 0x07); 776 777 /* Determine supported Cipher Suites -- Requires two calls */ 778 p = get_lan_param(intf, chan, IPMI_LANP_RMCP_CIPHER_SUPPORT); 779 if (p == NULL) 780 return -1; 781 else if (p->data != NULL) 782 { 783 unsigned char cipher_suite_count = p->data[0]; 784 p = get_lan_param(intf, chan, IPMI_LANP_RMCP_CIPHERS); 785 if (p == NULL) 786 return -1; 787 788 printf("%-24s: ", p->desc); 789 790 /* Now we're dangerous. There are only 15 fixed cipher 791 suite IDs, but the spec allows for 16 in the return data.*/ 792 if ((p->data != NULL) && (p->data_len <= 17)) 793 { 794 unsigned int i; 795 for (i = 0; (i < 16) && (i < cipher_suite_count); ++i) 796 { 797 printf("%s%d", 798 (i > 0? ",": ""), 799 p->data[i + 1]); 800 } 801 printf("\n"); 802 } 803 else 804 { 805 printf("None\n"); 806 } 807 } 808 809 /* RMCP+ Messaging Cipher Suite Privilege Levels */ 810 /* These are the privilege levels for the 15 fixed cipher suites */ 811 p = get_lan_param(intf, chan, IPMI_LANP_RMCP_PRIV_LEVELS); 812 if (p == NULL) 813 return -1; 814 if ((p->data != NULL) && (p->data_len == 9)) 815 { 816 printf("%-24s: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", p->desc, 817 priv_level_to_char(p->data[1] & 0x0F), 818 priv_level_to_char(p->data[1] >> 4), 819 priv_level_to_char(p->data[2] & 0x0F), 820 priv_level_to_char(p->data[2] >> 4), 821 priv_level_to_char(p->data[3] & 0x0F), 822 priv_level_to_char(p->data[3] >> 4), 823 priv_level_to_char(p->data[4] & 0x0F), 824 priv_level_to_char(p->data[4] >> 4), 825 priv_level_to_char(p->data[5] & 0x0F), 826 priv_level_to_char(p->data[5] >> 4), 827 priv_level_to_char(p->data[6] & 0x0F), 828 priv_level_to_char(p->data[6] >> 4), 829 priv_level_to_char(p->data[7] & 0x0F), 830 priv_level_to_char(p->data[7] >> 4), 831 priv_level_to_char(p->data[8] & 0x0F)); 832 833 /* Now print a legend */ 834 printf("%-24s: %s\n", "", " X=Cipher Suite Unused"); 835 printf("%-24s: %s\n", "", " c=CALLBACK"); 836 printf("%-24s: %s\n", "", " u=USER"); 837 printf("%-24s: %s\n", "", " o=OPERATOR"); 838 printf("%-24s: %s\n", "", " a=ADMIN"); 839 printf("%-24s: %s\n", "", " O=OEM"); 840 } 841 else 842 printf("%-24s: Not Available\n", p->desc); 843 844 /* Bad Password Threshold */ 845 p = get_lan_param(intf, chan, IPMI_LANP_BAD_PASS_THRESH); 846 if (p == NULL) 847 return -1; 848 if ((p->data != NULL) && (p->data_len == 6)) { 849 int tmp; 850 851 printf("%-24s: %d\n", p->desc, p->data[1]); 852 printf("%-24s: %s\n", "Invalid password disable", 853 p->data[0] & 1 ? "yes" : "no" ); 854 tmp = p->data[2] + (p->data[3] << 8); 855 printf("%-24s: %d\n", "Attempt Count Reset Int.", tmp * 10); 856 tmp = p->data[4] + (p->data[5] << 8); 857 printf("%-24s: %d\n", "User Lockout Interval", tmp * 10); 858 } else { 859 printf("%-24s: Not Available\n", p->desc); 860 } 861 862 return 0; 863 } 864 865 /* Configure Authentication Types */ 866 /* TODO - probably some code duplication going on ??? */ 867 static int 868 ipmi_lan_set_auth(struct ipmi_intf * intf, uint8_t chan, char * level, char * types) 869 { 870 uint8_t data[5]; 871 uint8_t authtype = 0; 872 char * p; 873 struct lan_param * lp; 874 875 if (level == NULL || types == NULL) 876 return -1; 877 878 lp = get_lan_param(intf, chan, IPMI_LANP_AUTH_TYPE_ENABLE); 879 if (lp == NULL) 880 return -1; 881 if (lp->data == NULL) 882 return -1; 883 884 lprintf(LOG_DEBUG, "%-24s: callback=0x%02x user=0x%02x operator=0x%02x admin=0x%02x oem=0x%02x", 885 lp->desc, lp->data[0], lp->data[1], lp->data[2], lp->data[3], lp->data[4]); 886 887 memset(data, 0, 5); 888 memcpy(data, lp->data, 5); 889 890 p = types; 891 while (p) { 892 if (strncasecmp(p, "none", 4) == 0) 893 authtype |= 1 << IPMI_SESSION_AUTHTYPE_NONE; 894 else if (strncasecmp(p, "md2", 3) == 0) 895 authtype |= 1 << IPMI_SESSION_AUTHTYPE_MD2; 896 else if (strncasecmp(p, "md5", 3) == 0) 897 authtype |= 1 << IPMI_SESSION_AUTHTYPE_MD5; 898 else if ((strncasecmp(p, "password", 8) == 0) || 899 (strncasecmp(p, "key", 3) == 0)) 900 authtype |= 1 << IPMI_SESSION_AUTHTYPE_KEY; 901 else if (strncasecmp(p, "oem", 3) == 0) 902 authtype |= 1 << IPMI_SESSION_AUTHTYPE_OEM; 903 else 904 lprintf(LOG_WARNING, "Invalid authentication type: %s", p); 905 p = strchr(p, ','); 906 if (p) 907 p++; 908 } 909 910 p = level; 911 while (p) { 912 if (strncasecmp(p, "callback", 8) == 0) 913 data[0] = authtype; 914 else if (strncasecmp(p, "user", 4) == 0) 915 data[1] = authtype; 916 else if (strncasecmp(p, "operator", 8) == 0) 917 data[2] = authtype; 918 else if (strncasecmp(p, "admin", 5) == 0) 919 data[3] = authtype; 920 else 921 lprintf(LOG_WARNING, "Invalid authentication level: %s", p); 922 p = strchr(p, ','); 923 if (p) 924 p++; 925 } 926 927 if (verbose > 1) 928 printbuf(data, 5, "authtype data"); 929 930 return set_lan_param(intf, chan, IPMI_LANP_AUTH_TYPE_ENABLE, data, 5); 931 } 932 933 static int 934 ipmi_lan_set_password(struct ipmi_intf *intf, 935 uint8_t user_id, const char *password) 936 { 937 int ccode = 0; 938 ccode = _ipmi_set_user_password(intf, user_id, 939 IPMI_PASSWORD_SET_PASSWORD, password, 0); 940 if (eval_ccode(ccode) != 0) { 941 lprintf(LOG_ERR, "Unable to Set LAN Password for user %d", 942 user_id); 943 return (-1); 944 } 945 /* adjust our session password 946 * or we will no longer be able to communicate with BMC 947 */ 948 ipmi_intf_session_set_password(intf, (char *)password); 949 printf("Password %s for user %d\n", 950 (password == NULL) ? "cleared" : "set", user_id); 951 952 return 0; 953 } 954 955 /* ipmi_set_alert_enable - enable/disable PEF alerting for given channel. 956 * 957 * @channel - IPMI channel 958 * @enable - whether to enable/disable PEF alerting for given channel 959 * 960 * returns - 0 on success, (-1) on error. 961 */ 962 static int 963 ipmi_set_alert_enable(struct ipmi_intf *intf, uint8_t channel, uint8_t enable) 964 { 965 struct channel_access_t channel_access; 966 int ccode = 0; 967 memset(&channel_access, 0, sizeof(channel_access)); 968 channel_access.channel = channel; 969 ccode = _ipmi_get_channel_access(intf, &channel_access, 0); 970 if (eval_ccode(ccode) != 0) { 971 lprintf(LOG_ERR, 972 "Unable to Get Channel Access(non-volatile) for channel %d", 973 channel); 974 return (-1); 975 } 976 if (enable != 0) { 977 channel_access.alerting = 1; 978 } else { 979 channel_access.alerting = 0; 980 } 981 /* non-volatile */ 982 ccode = _ipmi_set_channel_access(intf, channel_access, 1, 0); 983 if (eval_ccode(ccode) != 0) { 984 lprintf(LOG_ERR, 985 "Unable to Set Channel Access(non-volatile) for channel %d", 986 channel); 987 return (-1); 988 } 989 /* volatile */ 990 ccode = _ipmi_set_channel_access(intf, channel_access, 2, 0); 991 if (eval_ccode(ccode) != 0) { 992 lprintf(LOG_ERR, 993 "Unable to Set Channel Access(volatile) for channel %d", 994 channel); 995 return (-1); 996 } 997 printf("PEF alerts for channel %d %s.\n", 998 channel, 999 (enable) ? "enabled" : "disabled"); 1000 return 0; 1001 } 1002 1003 /* ipmi_set_channel_access - enable/disable IPMI messaging for given channel and 1004 * set Privilege Level to Administrator. 1005 * 1006 * @channel - IPMI channel 1007 * @enable - whether to enable/disable IPMI messaging for given channel. 1008 * 1009 * returns - 0 on success, (-1) on error 1010 */ 1011 static int 1012 ipmi_set_channel_access(struct ipmi_intf *intf, uint8_t channel, 1013 uint8_t enable) 1014 { 1015 struct channel_access_t channel_access; 1016 int ccode = 0; 1017 memset(&channel_access, 0, sizeof(channel_access)); 1018 channel_access.channel = channel; 1019 /* Get Non-Volatile Channel Access first */ 1020 ccode = _ipmi_get_channel_access(intf, &channel_access, 0); 1021 if (eval_ccode(ccode) != 0) { 1022 lprintf(LOG_ERR, 1023 "Unable to Get Channel Access(non-volatile) for channel %d", 1024 channel); 1025 return (-1); 1026 } 1027 1028 if (enable != 0) { 1029 channel_access.access_mode = 2; 1030 } else { 1031 channel_access.access_mode = 0; 1032 } 1033 channel_access.privilege_limit = 0x04; 1034 ccode = _ipmi_set_channel_access(intf, channel_access, 1, 1); 1035 if (eval_ccode(ccode) != 0) { 1036 lprintf(LOG_ERR, 1037 "Unable to Set Channel Access(non-volatile) for channel %d", 1038 channel); 1039 return (-1); 1040 } 1041 1042 memset(&channel_access, 0, sizeof(channel_access)); 1043 channel_access.channel = channel; 1044 /* Get Volatile Channel Access */ 1045 ccode = _ipmi_get_channel_access(intf, &channel_access, 1); 1046 if (eval_ccode(ccode) != 0) { 1047 lprintf(LOG_ERR, 1048 "Unable to Get Channel Access(volatile) for channel %d", 1049 channel); 1050 return (-1); 1051 } 1052 1053 if (enable != 0) { 1054 channel_access.access_mode = 2; 1055 } else { 1056 channel_access.access_mode = 0; 1057 } 1058 channel_access.privilege_limit = 0x04; 1059 ccode = _ipmi_set_channel_access(intf, channel_access, 2, 2); 1060 if (eval_ccode(ccode) != 0) { 1061 lprintf(LOG_ERR, 1062 "Unable to Set Channel Access(volatile) for channel %d", 1063 channel); 1064 return (-1); 1065 } 1066 1067 /* can't send close session if access off so abort instead */ 1068 if (enable == 0) { 1069 intf->abort = 1; 1070 } 1071 printf("Set Channel Access for channel %d was successful.\n", 1072 channel); 1073 return 0; 1074 } 1075 1076 /* ipmi_set_user_access - set admin access for given user and channel. 1077 * 1078 * @intf - IPMI interface 1079 * @channel - IPMI channel 1080 * @user_id - IPMI User ID 1081 * 1082 * returns - 0 on success, (-1) on error. 1083 */ 1084 static int 1085 ipmi_set_user_access(struct ipmi_intf *intf, uint8_t channel, uint8_t user_id) 1086 { 1087 struct user_access_t user_access; 1088 int ccode = 0; 1089 memset(&user_access, 0, sizeof(user_access)); 1090 user_access.channel = channel; 1091 user_access.user_id = user_id; 1092 user_access.privilege_limit = 0x04; 1093 1094 ccode = _ipmi_set_user_access(intf, &user_access, 1); 1095 if (eval_ccode(ccode) != 0) { 1096 lprintf(LOG_ERR, "Set User Access for channel %d failed", 1097 channel); 1098 return (-1); 1099 } else { 1100 printf("Set User Access for channel %d was successful.", 1101 channel); 1102 return 0; 1103 } 1104 } 1105 1106 /* get_cmdline_macaddr - parse-out MAC address from given string and store it 1107 * into buffer. 1108 * 1109 * @arg: string to be parsed. 1110 * @buf: buffer of 6 to hold parsed MAC address. 1111 * 1112 * returns zero on success, (-1) on error and error message is printed-out. 1113 */ 1114 static int 1115 get_cmdline_macaddr(char *arg, uint8_t *buf) 1116 { 1117 uint32_t m1 = 0; 1118 uint32_t m2 = 0; 1119 uint32_t m3 = 0; 1120 uint32_t m4 = 0; 1121 uint32_t m5 = 0; 1122 uint32_t m6 = 0; 1123 if (sscanf(arg, "%02x:%02x:%02x:%02x:%02x:%02x", 1124 &m1, &m2, &m3, &m4, &m5, &m6) != 6) { 1125 lprintf(LOG_ERR, "Invalid MAC address: %s", arg); 1126 return -1; 1127 } 1128 if (m1 > UINT8_MAX || m2 > UINT8_MAX 1129 || m3 > UINT8_MAX || m4 > UINT8_MAX 1130 || m5 > UINT8_MAX || m6 > UINT8_MAX) { 1131 lprintf(LOG_ERR, "Invalid MAC address: %s", arg); 1132 return -1; 1133 } 1134 buf[0] = (uint8_t)m1; 1135 buf[1] = (uint8_t)m2; 1136 buf[2] = (uint8_t)m3; 1137 buf[3] = (uint8_t)m4; 1138 buf[4] = (uint8_t)m5; 1139 buf[5] = (uint8_t)m6; 1140 return 0; 1141 } 1142 1143 1144 static int 1145 get_cmdline_cipher_suite_priv_data(char * arg, uint8_t * buf) 1146 { 1147 int i, ret = 0; 1148 1149 if (strlen(arg) != 15) 1150 { 1151 lprintf(LOG_ERR, "Invalid privilege specification length: %d", 1152 strlen(arg)); 1153 return -1; 1154 } 1155 1156 /* 1157 * The first byte is reserved (0). The rest of the buffer is setup 1158 * so that each nibble holds the maximum privilege level available for 1159 * that cipher suite number. The number of nibbles (15) matches the number 1160 * of fixed cipher suite IDs. This command documentation mentions 16 IDs 1161 * but table 22-19 shows that there are only 15 (0-14). 1162 * 1163 * data 1 - reserved 1164 * data 2 - maximum priv level for first (LSN) and second (MSN) ciphers 1165 * data 3 - maximum priv level for third (LSN) and fourth (MSN) ciphers 1166 * data 9 - maximum priv level for 15th (LSN) cipher. 1167 */ 1168 memset(buf, 0, 9); 1169 for (i = 0; i < 15; ++i) 1170 { 1171 unsigned char priv_level = IPMI_SESSION_PRIV_ADMIN; 1172 1173 switch (arg[i]) 1174 { 1175 case 'X': 1176 priv_level = IPMI_SESSION_PRIV_UNSPECIFIED; /* 0 */ 1177 break; 1178 case 'c': 1179 priv_level = IPMI_SESSION_PRIV_CALLBACK; /* 1 */ 1180 break; 1181 case 'u': 1182 priv_level = IPMI_SESSION_PRIV_USER; /* 2 */ 1183 break; 1184 case 'o': 1185 priv_level = IPMI_SESSION_PRIV_OPERATOR; /* 3 */ 1186 break; 1187 case 'a': 1188 priv_level = IPMI_SESSION_PRIV_ADMIN; /* 4 */ 1189 break; 1190 case 'O': 1191 priv_level = IPMI_SESSION_PRIV_OEM; /* 5 */ 1192 break; 1193 default: 1194 lprintf(LOG_ERR, "Invalid privilege specification char: %c", 1195 arg[i]); 1196 ret = -1; 1197 break; 1198 } 1199 1200 if (ret != 0) 1201 break; 1202 else 1203 { 1204 if ((i + 1) % 2) 1205 { 1206 // Odd number cipher suites will be in the LSN 1207 buf[1 + (i / 2)] += priv_level; 1208 } 1209 else 1210 { 1211 // Even number cipher suites will be in the MSN 1212 buf[1 + (i / 2)] += (priv_level << 4); 1213 } 1214 } 1215 } 1216 1217 return ret; 1218 } 1219 1220 1221 static int 1222 get_cmdline_ipaddr(char * arg, uint8_t * buf) 1223 { 1224 uint32_t ip1, ip2, ip3, ip4; 1225 if (sscanf(arg, 1226 "%" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32, 1227 &ip1, &ip2, &ip3, &ip4) != 4) { 1228 lprintf(LOG_ERR, "Invalid IP address: %s", arg); 1229 return (-1); 1230 } 1231 if (ip1 > UINT8_MAX || ip2 > UINT8_MAX 1232 || ip3 > UINT8_MAX || ip4 > UINT8_MAX) { 1233 lprintf(LOG_ERR, "Invalid IP address: %s", arg); 1234 return (-1); 1235 } 1236 buf[0] = (uint8_t)ip1; 1237 buf[1] = (uint8_t)ip2; 1238 buf[2] = (uint8_t)ip3; 1239 buf[3] = (uint8_t)ip4; 1240 return 0; 1241 } 1242 1243 static int 1244 ipmi_lan_set_vlan_id(struct ipmi_intf *intf, uint8_t chan, char *string) 1245 { 1246 uint8_t data[2]; 1247 int rc; 1248 1249 if (string == NULL) { 1250 data[0] = 0; 1251 data[1] = 0; 1252 } 1253 else { 1254 int id = 0; 1255 if (str2int(string, &id) != 0) { 1256 lprintf(LOG_ERR, "Given VLAN ID '%s' is invalid.", string); 1257 return (-1); 1258 } 1259 1260 if (id < 1 || id > 4094) { 1261 lprintf(LOG_NOTICE, "VLAN ID must be between 1 and 4094."); 1262 return (-1); 1263 } 1264 else { 1265 data[0] = (uint8_t)id; 1266 data[1] = (uint8_t)(id >> 8) | 0x80; 1267 } 1268 } 1269 rc = set_lan_param(intf, chan, IPMI_LANP_VLAN_ID, data, 2); 1270 return rc; 1271 } 1272 1273 static int 1274 ipmi_lan_set_vlan_priority(struct ipmi_intf *intf, uint8_t chan, char *string) 1275 { 1276 uint8_t data; 1277 int rc; 1278 int priority = 0; 1279 if (str2int(string, &priority) != 0) { 1280 lprintf(LOG_ERR, "Given VLAN priority '%s' is invalid.", string); 1281 return (-1); 1282 } 1283 1284 if (priority < 0 || priority > 7) { 1285 lprintf(LOG_NOTICE, "VLAN priority must be between 0 and 7."); 1286 return (-1); 1287 } 1288 data = (uint8_t)priority; 1289 rc = set_lan_param(intf, chan, IPMI_LANP_VLAN_PRIORITY, &data, 1); 1290 return rc; 1291 } 1292 1293 static void 1294 print_lan_set_bad_pass_thresh_usage(void) 1295 { 1296 lprintf(LOG_NOTICE, 1297 "lan set <chanel> bad_pass_thresh <thresh_num> <1|0> <reset_interval> <lockout_interval>\n" 1298 " <thresh_num> Bad Pasword Threshold number.\n" 1299 " <1|0> 1 = generate a Session Audit sensor event.\n" 1300 " 0 = do not generate an event.\n" 1301 " <reset_interval> Attempt Count Reset Interval. In tens of seconds.\n" 1302 " <lockount_interval> User Lockout Interval. In tens of seconds."); 1303 } 1304 1305 /* get_cmdline_bad_pass_thresh - parse-out bad password threshold from given 1306 * string and store it into buffer. 1307 * 1308 * @arg: string to be parsed. 1309 * @buf: buffer of 6 to hold parsed Bad Password Threshold. 1310 * 1311 * returns zero on success, (-1) on error. 1312 */ 1313 static int 1314 get_cmdline_bad_pass_thresh(char *argv[], uint8_t *buf) 1315 { 1316 uint16_t reset, lockout; 1317 1318 if (str2uchar(argv[0], &buf[1])) { 1319 return -1; 1320 } 1321 1322 if (str2uchar(argv[1], &buf[0]) || buf[0] > 1) { 1323 return -1; 1324 } 1325 1326 if (str2ushort(argv[2], &reset)) { 1327 return -1; 1328 } 1329 1330 if (str2ushort(argv[3], &lockout)) { 1331 return -1; 1332 } 1333 1334 /* store parsed data */ 1335 buf[2] = reset & 0xFF; 1336 buf[3] = reset >> 8; 1337 buf[4] = lockout & 0xFF; 1338 buf[5] = lockout >> 8; 1339 return 0; 1340 } 1341 1342 static int 1343 ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) 1344 { 1345 uint8_t data[32]; 1346 uint8_t chan; 1347 int rc = 0; 1348 1349 if (argc < 2) { 1350 print_lan_set_usage(); 1351 return (-1); 1352 } 1353 1354 if (strncmp(argv[0], "help", 4) == 0 || 1355 strncmp(argv[1], "help", 4) == 0) { 1356 print_lan_set_usage(); 1357 return 0; 1358 } 1359 1360 if (str2uchar(argv[0], &chan) != 0) { 1361 lprintf(LOG_ERR, "Invalid channel: %s", argv[0]); 1362 return (-1); 1363 } 1364 1365 /* find type of channel and only accept 802.3 LAN */ 1366 if (!is_lan_channel(intf, chan)) { 1367 lprintf(LOG_ERR, "Channel %d is not a LAN channel!", chan); 1368 print_lan_set_usage(); 1369 return -1; 1370 } 1371 1372 memset(&data, 0, sizeof(data)); 1373 1374 /* set user access */ 1375 if (strncmp(argv[1], "user", 4) == 0) { 1376 rc = ipmi_set_user_access(intf, chan, 1); 1377 } 1378 /* set channel access mode */ 1379 else if (strncmp(argv[1], "access", 6) == 0) { 1380 if (argc < 3) { 1381 print_lan_set_access_usage(); 1382 return (-1); 1383 } 1384 else if (strncmp(argv[2], "help", 4) == 0) { 1385 print_lan_set_access_usage(); 1386 return 0; 1387 } 1388 else if (strncmp(argv[2], "on", 2) == 0) { 1389 rc = ipmi_set_channel_access(intf, chan, 1); 1390 } 1391 else if (strncmp(argv[2], "off", 3) == 0) { 1392 rc = ipmi_set_channel_access(intf, chan, 0); 1393 } 1394 else { 1395 print_lan_set_access_usage(); 1396 return (-1); 1397 } 1398 } 1399 /* set ARP control */ 1400 else if (strncmp(argv[1], "arp", 3) == 0) { 1401 if (argc < 3) { 1402 print_lan_set_arp_usage(); 1403 return (-1); 1404 } 1405 else if (strncmp(argv[2], "help", 4) == 0) { 1406 print_lan_set_arp_usage(); 1407 } 1408 else if (strncmp(argv[2], "interval", 8) == 0) { 1409 uint8_t interval = 0; 1410 if (str2uchar(argv[3], &interval) != 0) { 1411 lprintf(LOG_ERR, "Given ARP interval '%s' is invalid.", argv[3]); 1412 return (-1); 1413 } 1414 rc = lan_set_arp_interval(intf, chan, interval); 1415 } 1416 else if (strncmp(argv[2], "generate", 8) == 0) { 1417 if (argc < 4) { 1418 print_lan_set_arp_usage(); 1419 return (-1); 1420 } 1421 else if (strncmp(argv[3], "on", 2) == 0) 1422 rc = lan_set_arp_generate(intf, chan, 1); 1423 else if (strncmp(argv[3], "off", 3) == 0) 1424 rc = lan_set_arp_generate(intf, chan, 0); 1425 else { 1426 print_lan_set_arp_usage(); 1427 return (-1); 1428 } 1429 } 1430 else if (strncmp(argv[2], "respond", 7) == 0) { 1431 if (argc < 4) { 1432 print_lan_set_arp_usage(); 1433 return (-1); 1434 } 1435 else if (strncmp(argv[3], "on", 2) == 0) 1436 rc = lan_set_arp_respond(intf, chan, 1); 1437 else if (strncmp(argv[3], "off", 3) == 0) 1438 rc = lan_set_arp_respond(intf, chan, 0); 1439 else { 1440 print_lan_set_arp_usage(); 1441 return (-1); 1442 } 1443 } 1444 else { 1445 print_lan_set_arp_usage(); 1446 } 1447 } 1448 /* set authentication types */ 1449 else if (strncmp(argv[1], "auth", 4) == 0) { 1450 if (argc < 3) { 1451 print_lan_set_auth_usage(); 1452 return (-1); 1453 } 1454 else if (strncmp(argv[2], "help", 4) == 0) { 1455 print_lan_set_auth_usage(); 1456 return 0; 1457 } else { 1458 rc = ipmi_lan_set_auth(intf, chan, argv[2], argv[3]); 1459 } 1460 } 1461 /* ip address source */ 1462 else if (strncmp(argv[1], "ipsrc", 5) == 0) { 1463 if (argc < 3) { 1464 print_lan_set_ipsrc_usage(); 1465 return (-1); 1466 } 1467 else if (strncmp(argv[2], "help", 4) == 0) { 1468 print_lan_set_ipsrc_usage(); 1469 return 0; 1470 } 1471 else if (strncmp(argv[2], "none", 4) == 0) 1472 data[0] = 0; 1473 else if (strncmp(argv[2], "static", 5) == 0) 1474 data[0] = 1; 1475 else if (strncmp(argv[2], "dhcp", 4) == 0) 1476 data[0] = 2; 1477 else if (strncmp(argv[2], "bios", 4) == 0) 1478 data[0] = 3; 1479 else { 1480 print_lan_set_ipsrc_usage(); 1481 return -1; 1482 } 1483 rc = set_lan_param(intf, chan, IPMI_LANP_IP_ADDR_SRC, data, 1); 1484 } 1485 /* session password 1486 * not strictly a lan setting, but its used for lan connections */ 1487 else if (strncmp(argv[1], "password", 8) == 0) { 1488 rc = ipmi_lan_set_password(intf, 1, argv[2]); 1489 } 1490 /* snmp community string */ 1491 else if (strncmp(argv[1], "snmp", 4) == 0) { 1492 if (argc < 3) { 1493 print_lan_set_snmp_usage(); 1494 return (-1); 1495 } 1496 else if (strncmp(argv[2], "help", 4) == 0) { 1497 print_lan_set_snmp_usage(); 1498 return 0; 1499 } else { 1500 memcpy(data, argv[2], __min(strlen(argv[2]), 18)); 1501 printf("Setting LAN %s to %s\n", 1502 ipmi_lan_params[IPMI_LANP_SNMP_STRING].desc, data); 1503 rc = set_lan_param(intf, chan, IPMI_LANP_SNMP_STRING, data, 18); 1504 } 1505 } 1506 /* ip address */ 1507 else if (strncmp(argv[1], "ipaddr", 6) == 0) { 1508 if(argc != 3) 1509 { 1510 print_lan_set_usage(); 1511 return -1; 1512 } 1513 rc = get_cmdline_ipaddr(argv[2], data); 1514 if (rc == 0) { 1515 printf("Setting LAN %s to %d.%d.%d.%d\n", 1516 ipmi_lan_params[IPMI_LANP_IP_ADDR].desc, 1517 data[0], data[1], data[2], data[3]); 1518 rc = set_lan_param(intf, chan, IPMI_LANP_IP_ADDR, data, 4); 1519 } 1520 } 1521 /* network mask */ 1522 else if (strncmp(argv[1], "netmask", 7) == 0) { 1523 if(argc != 3) 1524 { 1525 print_lan_set_usage(); 1526 return -1; 1527 } 1528 rc = get_cmdline_ipaddr(argv[2], data); 1529 if (rc == 0) { 1530 printf("Setting LAN %s to %d.%d.%d.%d\n", 1531 ipmi_lan_params[IPMI_LANP_SUBNET_MASK].desc, 1532 data[0], data[1], data[2], data[3]); 1533 rc = set_lan_param(intf, chan, IPMI_LANP_SUBNET_MASK, data, 4); 1534 } 1535 } 1536 /* mac address */ 1537 else if (strncmp(argv[1], "macaddr", 7) == 0) { 1538 if(argc != 3) 1539 { 1540 print_lan_set_usage(); 1541 return -1; 1542 } 1543 rc = get_cmdline_macaddr(argv[2], data); 1544 if (rc == 0) { 1545 printf("Setting LAN %s to %02x:%02x:%02x:%02x:%02x:%02x\n", 1546 ipmi_lan_params[IPMI_LANP_MAC_ADDR].desc, 1547 data[0], data[1], data[2], data[3], data[4], data[5]); 1548 rc = set_lan_param(intf, chan, IPMI_LANP_MAC_ADDR, data, 6); 1549 } 1550 } 1551 /* default gateway settings */ 1552 else if (strncmp(argv[1], "defgw", 5) == 0) { 1553 if (argc < 4) { 1554 print_lan_set_defgw_usage(); 1555 return (-1); 1556 } 1557 else if (strncmp(argv[2], "help", 4) == 0) { 1558 print_lan_set_defgw_usage(); 1559 return 0; 1560 } 1561 else if ((strncmp(argv[2], "ipaddr", 5) == 0) && 1562 (get_cmdline_ipaddr(argv[3], data) == 0)) { 1563 printf("Setting LAN %s to %d.%d.%d.%d\n", 1564 ipmi_lan_params[IPMI_LANP_DEF_GATEWAY_IP].desc, 1565 data[0], data[1], data[2], data[3]); 1566 rc = set_lan_param(intf, chan, IPMI_LANP_DEF_GATEWAY_IP, data, 4); 1567 } 1568 else if ((strncmp(argv[2], "macaddr", 7) == 0) && 1569 (get_cmdline_macaddr(argv[3], data) == 0)) { 1570 printf("Setting LAN %s to %02x:%02x:%02x:%02x:%02x:%02x\n", 1571 ipmi_lan_params[IPMI_LANP_DEF_GATEWAY_MAC].desc, 1572 data[0], data[1], data[2], data[3], data[4], data[5]); 1573 rc = set_lan_param(intf, chan, IPMI_LANP_DEF_GATEWAY_MAC, data, 6); 1574 } 1575 else { 1576 print_lan_set_usage(); 1577 return -1; 1578 } 1579 } 1580 /* backup gateway settings */ 1581 else if (strncmp(argv[1], "bakgw", 5) == 0) { 1582 if (argc < 4) { 1583 print_lan_set_bakgw_usage(); 1584 return (-1); 1585 } 1586 else if (strncmp(argv[2], "help", 4) == 0) { 1587 print_lan_set_bakgw_usage(); 1588 return 0; 1589 } 1590 else if ((strncmp(argv[2], "ipaddr", 5) == 0) && 1591 (get_cmdline_ipaddr(argv[3], data) == 0)) { 1592 printf("Setting LAN %s to %d.%d.%d.%d\n", 1593 ipmi_lan_params[IPMI_LANP_BAK_GATEWAY_IP].desc, 1594 data[0], data[1], data[2], data[3]); 1595 rc = set_lan_param(intf, chan, IPMI_LANP_BAK_GATEWAY_IP, data, 4); 1596 } 1597 else if ((strncmp(argv[2], "macaddr", 7) == 0) && 1598 (get_cmdline_macaddr(argv[3], data) == 0)) { 1599 printf("Setting LAN %s to %02x:%02x:%02x:%02x:%02x:%02x\n", 1600 ipmi_lan_params[IPMI_LANP_BAK_GATEWAY_MAC].desc, 1601 data[0], data[1], data[2], data[3], data[4], data[5]); 1602 rc = set_lan_param(intf, chan, IPMI_LANP_BAK_GATEWAY_MAC, data, 6); 1603 } 1604 else { 1605 print_lan_set_usage(); 1606 return -1; 1607 } 1608 } 1609 else if (strncasecmp(argv[1], "vlan", 4) == 0) { 1610 if (argc < 4) { 1611 print_lan_set_vlan_usage(); 1612 return (-1); 1613 } 1614 else if (strncmp(argv[2], "help", 4) == 0) { 1615 print_lan_set_vlan_usage(); 1616 return 0; 1617 } 1618 else if (strncasecmp(argv[2], "id", 2) == 0) { 1619 if (strncasecmp(argv[3], "off", 3) == 0) { 1620 ipmi_lan_set_vlan_id(intf, chan, NULL); 1621 } 1622 else { 1623 ipmi_lan_set_vlan_id(intf, chan, argv[3]); 1624 } 1625 } 1626 else if (strncasecmp(argv[2], "priority", 8) == 0) { 1627 ipmi_lan_set_vlan_priority(intf, chan, argv[3]); 1628 } 1629 else { 1630 print_lan_set_vlan_usage(); 1631 return (-1); 1632 } 1633 } 1634 /* set PEF alerting on or off */ 1635 else if (strncasecmp(argv[1], "alert", 5) == 0) { 1636 if (argc < 3) { 1637 lprintf(LOG_NOTICE, "LAN set alert must be 'on' or 'off'"); 1638 return (-1); 1639 } 1640 else if (strncasecmp(argv[2], "on", 2) == 0 || 1641 strncasecmp(argv[2], "enable", 6) == 0) { 1642 printf("Enabling PEF alerts for LAN channel %d\n", chan); 1643 rc = ipmi_set_alert_enable(intf, chan, 1); 1644 } 1645 else if (strncasecmp(argv[2], "off", 3) == 0 || 1646 strncasecmp(argv[2], "disable", 7) == 0) { 1647 printf("Disabling PEF alerts for LAN channel %d\n", chan); 1648 rc = ipmi_set_alert_enable(intf, chan, 0); 1649 } 1650 else { 1651 lprintf(LOG_NOTICE, "LAN set alert must be 'on' or 'off'"); 1652 return 0; 1653 } 1654 } 1655 /* RMCP+ cipher suite privilege levels */ 1656 else if (strncmp(argv[1], "cipher_privs", 12) == 0) 1657 { 1658 if (argc != 3) { 1659 print_lan_set_cipher_privs_usage(); 1660 return (-1); 1661 } 1662 else if ((strncmp(argv[2], "help", 4) == 0) || 1663 get_cmdline_cipher_suite_priv_data(argv[2], data)) 1664 { 1665 print_lan_set_cipher_privs_usage(); 1666 return 0; 1667 } 1668 else 1669 { 1670 rc = set_lan_param(intf, chan, IPMI_LANP_RMCP_PRIV_LEVELS, data, 9); 1671 } 1672 } 1673 else if (strncmp(argv[1], "bad_pass_thresh", 15) == 0) 1674 { 1675 if (argc == 3 && strncmp(argv[2], "help", 4) == 0) { 1676 print_lan_set_bad_pass_thresh_usage(); 1677 return 0; 1678 } 1679 if (argc < 6 || get_cmdline_bad_pass_thresh(&argv[2], data)) { 1680 print_lan_set_bad_pass_thresh_usage(); 1681 return (-1); 1682 } 1683 rc = set_lan_param(intf, chan, IPMI_LANP_BAD_PASS_THRESH, data, 6); 1684 } 1685 else { 1686 print_lan_set_usage(); 1687 return (-1); 1688 } 1689 1690 return rc; 1691 } 1692 1693 1694 static int 1695 is_alert_destination(struct ipmi_intf * intf, uint8_t channel, uint8_t alert) 1696 { 1697 struct lan_param * p; 1698 1699 p = get_lan_param(intf, channel, IPMI_LANP_NUM_DEST); 1700 if (p == NULL) 1701 return 0; 1702 if (p->data == NULL) 1703 return 0; 1704 1705 if (alert <= (p->data[0] & 0xf)) 1706 return 1; 1707 else 1708 return 0; 1709 } 1710 1711 static int 1712 ipmi_lan_alert_print(struct ipmi_intf * intf, uint8_t channel, uint8_t alert) 1713 { 1714 # define PTYPE_LEN 4 1715 # define PADDR_LEN 13 1716 struct lan_param *lp_ptr = NULL; 1717 int isack = 0; 1718 uint8_t ptype[PTYPE_LEN]; 1719 uint8_t paddr[PADDR_LEN]; 1720 1721 lp_ptr = get_lan_param_select(intf, channel, IPMI_LANP_DEST_TYPE, alert); 1722 if (lp_ptr == NULL || lp_ptr->data == NULL 1723 || lp_ptr->data_len < PTYPE_LEN) { 1724 return (-1); 1725 } 1726 memcpy(ptype, lp_ptr->data, PTYPE_LEN); 1727 1728 lp_ptr = get_lan_param_select(intf, channel, IPMI_LANP_DEST_ADDR, alert); 1729 if (lp_ptr == NULL || lp_ptr->data == NULL 1730 || lp_ptr->data_len < PADDR_LEN) { 1731 return (-1); 1732 } 1733 memcpy(paddr, lp_ptr->data, PADDR_LEN); 1734 1735 printf("%-24s: %d\n", "Alert Destination", 1736 ptype[0]); 1737 1738 if (ptype[1] & 0x80) { 1739 isack = 1; 1740 } 1741 printf("%-24s: %s\n", "Alert Acknowledge", 1742 isack ? "Acknowledged" : "Unacknowledged"); 1743 1744 printf("%-24s: ", "Destination Type"); 1745 switch (ptype[1] & 0x7) { 1746 case 0: 1747 printf("PET Trap\n"); 1748 break; 1749 case 6: 1750 printf("OEM 1\n"); 1751 break; 1752 case 7: 1753 printf("OEM 2\n"); 1754 break; 1755 default: 1756 printf("Unknown\n"); 1757 break; 1758 } 1759 1760 printf("%-24s: %d\n", 1761 isack ? "Acknowledge Timeout" : "Retry Interval", 1762 ptype[2]); 1763 1764 printf("%-24s: %d\n", "Number of Retries", 1765 ptype[3] & 0x7); 1766 1767 if ((paddr[1] & 0xf0) != 0) { 1768 /* unknown address format */ 1769 printf("\n"); 1770 return 0; 1771 } 1772 1773 printf("%-24s: %s\n", "Alert Gateway", 1774 (paddr[2] & 1) ? "Backup" : "Default"); 1775 1776 printf("%-24s: %d.%d.%d.%d\n", "Alert IP Address", 1777 paddr[3], paddr[4], paddr[5], paddr[6]); 1778 1779 printf("%-24s: %02x:%02x:%02x:%02x:%02x:%02x\n", "Alert MAC Address", 1780 paddr[7], paddr[8], paddr[9], 1781 paddr[10], paddr[11], paddr[12]); 1782 1783 printf("\n"); 1784 return 0; 1785 } 1786 1787 static int 1788 ipmi_lan_alert_print_all(struct ipmi_intf * intf, uint8_t channel) 1789 { 1790 int j, ndest; 1791 struct lan_param * p; 1792 1793 p = get_lan_param(intf, channel, IPMI_LANP_NUM_DEST); 1794 if (p == NULL) 1795 return -1; 1796 if (p->data == NULL) 1797 return -1; 1798 ndest = p->data[0] & 0xf; 1799 1800 for (j=0; j<=ndest; j++) { 1801 ipmi_lan_alert_print(intf, channel, j); 1802 } 1803 1804 return 0; 1805 } 1806 1807 static int 1808 ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, 1809 int argc, char ** argv) 1810 { 1811 struct lan_param * p; 1812 uint8_t data[32], temp[32]; 1813 int rc = 0; 1814 1815 if (argc < 2) { 1816 print_lan_alert_set_usage(); 1817 return (-1); 1818 } 1819 1820 if (strncmp(argv[0], "help", 4) == 0 || 1821 strncmp(argv[1], "help", 4) == 0) { 1822 print_lan_alert_set_usage(); 1823 return 0; 1824 } 1825 1826 memset(data, 0, sizeof(data)); 1827 memset(temp, 0, sizeof(temp)); 1828 1829 /* alert destination ip address */ 1830 if (strncasecmp(argv[0], "ipaddr", 6) == 0 && 1831 (get_cmdline_ipaddr(argv[1], temp) == 0)) { 1832 /* get current parameter */ 1833 p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_ADDR, alert); 1834 if (p == NULL) { 1835 return (-1); 1836 } 1837 memcpy(data, p->data, p->data_len); 1838 /* set new ipaddr */ 1839 memcpy(data+3, temp, 4); 1840 printf("Setting LAN Alert %d IP Address to %d.%d.%d.%d\n", alert, 1841 data[3], data[4], data[5], data[6]); 1842 rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_ADDR, data, p->data_len); 1843 } 1844 /* alert destination mac address */ 1845 else if (strncasecmp(argv[0], "macaddr", 7) == 0 && 1846 (get_cmdline_macaddr(argv[1], temp) == 0)) { 1847 /* get current parameter */ 1848 p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_ADDR, alert); 1849 if (p == NULL) { 1850 return (-1); 1851 } 1852 memcpy(data, p->data, p->data_len); 1853 /* set new macaddr */ 1854 memcpy(data+7, temp, 6); 1855 printf("Setting LAN Alert %d MAC Address to " 1856 "%02x:%02x:%02x:%02x:%02x:%02x\n", alert, 1857 data[7], data[8], data[9], data[10], data[11], data[12]); 1858 rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_ADDR, data, p->data_len); 1859 } 1860 /* alert destination gateway selector */ 1861 else if (strncasecmp(argv[0], "gateway", 7) == 0) { 1862 /* get current parameter */ 1863 p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_ADDR, alert); 1864 if (p == NULL) { 1865 return (-1); 1866 } 1867 memcpy(data, p->data, p->data_len); 1868 1869 if (strncasecmp(argv[1], "def", 3) == 0 || 1870 strncasecmp(argv[1], "default", 7) == 0) { 1871 printf("Setting LAN Alert %d to use Default Gateway\n", alert); 1872 data[2] = 0; 1873 } 1874 else if (strncasecmp(argv[1], "bak", 3) == 0 || 1875 strncasecmp(argv[1], "backup", 6) == 0) { 1876 printf("Setting LAN Alert %d to use Backup Gateway\n", alert); 1877 data[2] = 1; 1878 } 1879 else { 1880 print_lan_alert_set_usage(); 1881 return -1; 1882 } 1883 1884 rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_ADDR, data, p->data_len); 1885 } 1886 /* alert acknowledgement */ 1887 else if (strncasecmp(argv[0], "ack", 3) == 0) { 1888 /* get current parameter */ 1889 p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_TYPE, alert); 1890 if (p == NULL) { 1891 return (-1); 1892 } 1893 memcpy(data, p->data, p->data_len); 1894 1895 if (strncasecmp(argv[1], "on", 2) == 0 || 1896 strncasecmp(argv[1], "yes", 3) == 0) { 1897 printf("Setting LAN Alert %d to Acknowledged\n", alert); 1898 data[1] |= 0x80; 1899 } 1900 else if (strncasecmp(argv[1], "off", 3) == 0 || 1901 strncasecmp(argv[1], "no", 2) == 0) { 1902 printf("Setting LAN Alert %d to Unacknowledged\n", alert); 1903 data[1] &= ~0x80; 1904 } 1905 else { 1906 print_lan_alert_set_usage(); 1907 return -1; 1908 } 1909 rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_TYPE, data, p->data_len); 1910 } 1911 /* alert destination type */ 1912 else if (strncasecmp(argv[0], "type", 4) == 0) { 1913 /* get current parameter */ 1914 p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_TYPE, alert); 1915 if (p == NULL) { 1916 return (-1); 1917 } 1918 memcpy(data, p->data, p->data_len); 1919 1920 if (strncasecmp(argv[1], "pet", 3) == 0) { 1921 printf("Setting LAN Alert %d destination to PET Trap\n", alert); 1922 data[1] &= ~0x07; 1923 } 1924 else if (strncasecmp(argv[1], "oem1", 4) == 0) { 1925 printf("Setting LAN Alert %d destination to OEM 1\n", alert); 1926 data[1] &= ~0x07; 1927 data[1] |= 0x06; 1928 } 1929 else if (strncasecmp(argv[1], "oem2", 4) == 0) { 1930 printf("Setting LAN Alert %d destination to OEM 2\n", alert); 1931 data[1] |= 0x07; 1932 } 1933 else { 1934 print_lan_alert_set_usage(); 1935 return -1; 1936 } 1937 rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_TYPE, data, p->data_len); 1938 } 1939 /* alert acknowledge timeout or retry interval */ 1940 else if (strncasecmp(argv[0], "time", 4) == 0) { 1941 /* get current parameter */ 1942 p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_TYPE, alert); 1943 if (p == NULL) { 1944 return (-1); 1945 } 1946 memcpy(data, p->data, p->data_len); 1947 1948 if (str2uchar(argv[1], &data[2]) != 0) { 1949 lprintf(LOG_ERR, "Invalid time: %s", argv[1]); 1950 return (-1); 1951 } 1952 printf("Setting LAN Alert %d timeout/retry to %d seconds\n", alert, data[2]); 1953 rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_TYPE, data, p->data_len); 1954 } 1955 /* number of retries */ 1956 else if (strncasecmp(argv[0], "retry", 5) == 0) { 1957 /* get current parameter */ 1958 p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_TYPE, alert); 1959 if (p == NULL) { 1960 return (-1); 1961 } 1962 memcpy(data, p->data, p->data_len); 1963 1964 if (str2uchar(argv[1], &data[3]) != 0) { 1965 lprintf(LOG_ERR, "Invalid retry: %s", argv[1]); 1966 return (-1); 1967 } 1968 data[3] = data[3] & 0x7; 1969 printf("Setting LAN Alert %d number of retries to %d\n", alert, data[3]); 1970 rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_TYPE, data, p->data_len); 1971 } 1972 else { 1973 print_lan_alert_set_usage(); 1974 return -1; 1975 } 1976 1977 return rc; 1978 } 1979 1980 static int 1981 ipmi_lan_alert(struct ipmi_intf * intf, int argc, char ** argv) 1982 { 1983 uint8_t alert; 1984 uint8_t channel = 1; 1985 1986 if (argc < 1) { 1987 print_lan_alert_print_usage(); 1988 print_lan_alert_set_usage(); 1989 return (-1); 1990 } 1991 else if (strncasecmp(argv[0], "help", 4) == 0) { 1992 print_lan_alert_print_usage(); 1993 print_lan_alert_set_usage(); 1994 return 0; 1995 } 1996 1997 /* alert print [channel] [alert] */ 1998 if (strncasecmp(argv[0], "print", 5) == 0) { 1999 if (argc < 2) { 2000 channel = find_lan_channel(intf, 1); 2001 if (!is_lan_channel(intf, channel)) { 2002 lprintf(LOG_ERR, "Channel %d is not a LAN channel", channel); 2003 return -1; 2004 } 2005 return ipmi_lan_alert_print_all(intf, channel); 2006 } 2007 2008 if (strncasecmp(argv[1], "help", 4) == 0) { 2009 print_lan_alert_print_usage(); 2010 return 0; 2011 } 2012 2013 if (str2uchar(argv[1], &channel) != 0) { 2014 lprintf(LOG_ERR, "Invalid channel: %s", argv[1]); 2015 return (-1); 2016 } 2017 if (!is_lan_channel(intf, channel)) { 2018 lprintf(LOG_ERR, "Channel %d is not a LAN channel", channel); 2019 return -1; 2020 } 2021 2022 if (argc < 3) 2023 return ipmi_lan_alert_print_all(intf, channel); 2024 2025 if (str2uchar(argv[2], &alert) != 0) { 2026 lprintf(LOG_ERR, "Invalid alert: %s", argv[2]); 2027 return (-1); 2028 } 2029 if (is_alert_destination(intf, channel, alert) == 0) { 2030 lprintf(LOG_ERR, "Alert %d is not a valid destination", alert); 2031 return -1; 2032 } 2033 return ipmi_lan_alert_print(intf, channel, alert); 2034 } 2035 2036 /* alert set <channel> <alert> [option] */ 2037 if (strncasecmp(argv[0], "set", 3) == 0) { 2038 if (argc < 5) { 2039 print_lan_alert_set_usage(); 2040 return (-1); 2041 } 2042 else if (strncasecmp(argv[1], "help", 4) == 0) { 2043 print_lan_alert_set_usage(); 2044 return 0; 2045 } 2046 2047 if (str2uchar(argv[1], &channel) != 0) { 2048 lprintf(LOG_ERR, "Invalid channel: %s", argv[1]); 2049 return (-1); 2050 } 2051 if (!is_lan_channel(intf, channel)) { 2052 lprintf(LOG_ERR, "Channel %d is not a LAN channel", channel); 2053 return -1; 2054 } 2055 2056 if (str2uchar(argv[2], &alert) != 0) { 2057 lprintf(LOG_ERR, "Invalid alert: %s", argv[2]); 2058 return (-1); 2059 } 2060 if (is_alert_destination(intf, channel, alert) == 0) { 2061 lprintf(LOG_ERR, "Alert %d is not a valid destination", alert); 2062 return -1; 2063 } 2064 2065 return ipmi_lan_alert_set(intf, channel, alert, argc-3, &(argv[3])); 2066 } 2067 2068 return 0; 2069 } 2070 2071 2072 static int 2073 ipmi_lan_stats_get(struct ipmi_intf * intf, uint8_t chan) 2074 { 2075 int rc = 0; 2076 struct ipmi_rs * rsp; 2077 struct ipmi_rq req; 2078 uint8_t msg_data[2]; 2079 uint16_t statsTemp; 2080 2081 if (!is_lan_channel(intf, chan)) { 2082 lprintf(LOG_ERR, "Channel %d is not a LAN channel", chan); 2083 return -1; 2084 } 2085 2086 /* From here, we are ready to get the stats */ 2087 2088 msg_data[0] = chan; 2089 msg_data[1] = 0; /* Don't clear */ 2090 2091 memset(&req, 0, sizeof(req)); 2092 req.msg.netfn = IPMI_NETFN_TRANSPORT; 2093 req.msg.cmd = IPMI_LAN_GET_STAT; 2094 req.msg.data = msg_data; 2095 req.msg.data_len = 2; 2096 2097 rsp = intf->sendrecv(intf, &req); 2098 if (rsp == NULL) { 2099 lprintf(LOG_ERR, "Get LAN Stats command failed"); 2100 return (-1); 2101 } 2102 2103 if (rsp->ccode > 0) { 2104 lprintf(LOG_ERR, "Get LAN Stats command failed: %s", 2105 val2str(rsp->ccode, completion_code_vals)); 2106 return (-1); 2107 } 2108 2109 if (verbose > 1) { 2110 uint8_t counter; 2111 printf("--- Rx Stats ---\n"); 2112 for (counter=0; counter<18; counter+=2) { 2113 printf("%02X", *(rsp->data + counter)); 2114 printf(" %02X - ", *(rsp->data + counter+1)); 2115 } 2116 printf("\n"); 2117 } 2118 2119 statsTemp = ((*(rsp->data + 0)) << 8) | (*(rsp->data + 1)); 2120 printf("IP Rx Packet : %d\n", statsTemp); 2121 2122 statsTemp = ((*(rsp->data + 2)) << 8) | (*(rsp->data + 3)); 2123 printf("IP Rx Header Errors : %u\n", statsTemp); 2124 2125 statsTemp = ((*(rsp->data + 4)) << 8) | (*(rsp->data + 5)); 2126 printf("IP Rx Address Errors : %u\n", statsTemp); 2127 2128 statsTemp = ((*(rsp->data + 6)) << 8) | (*(rsp->data + 7)); 2129 printf("IP Rx Fragmented : %u\n", statsTemp); 2130 2131 statsTemp = ((*(rsp->data + 8)) << 8) | (*(rsp->data + 9)); 2132 printf("IP Tx Packet : %u\n", statsTemp); 2133 2134 statsTemp = ((*(rsp->data +10)) << 8) | (*(rsp->data +11)); 2135 printf("UDP Rx Packet : %u\n", statsTemp); 2136 2137 statsTemp = ((*(rsp->data + 12)) << 8) | (*(rsp->data + 13)); 2138 printf("RMCP Rx Valid : %u\n", statsTemp); 2139 2140 statsTemp = ((*(rsp->data + 14)) << 8) | (*(rsp->data + 15)); 2141 printf("UDP Proxy Packet Received : %u\n", statsTemp); 2142 2143 statsTemp = ((*(rsp->data + 16)) << 8) | (*(rsp->data + 17)); 2144 printf("UDP Proxy Packet Dropped : %u\n", statsTemp); 2145 2146 return rc; 2147 } 2148 2149 2150 static int 2151 ipmi_lan_stats_clear(struct ipmi_intf * intf, uint8_t chan) 2152 { 2153 int rc = 0; 2154 struct ipmi_rs * rsp; 2155 struct ipmi_rq req; 2156 uint8_t msg_data[2]; 2157 2158 if (!is_lan_channel(intf, chan)) { 2159 lprintf(LOG_ERR, "Channel %d is not a LAN channel", chan); 2160 return -1; 2161 } 2162 2163 /* From here, we are ready to get the stats */ 2164 msg_data[0] = chan; 2165 msg_data[1] = 1; /* Clear */ 2166 2167 memset(&req, 0, sizeof(req)); 2168 req.msg.netfn = IPMI_NETFN_TRANSPORT; 2169 req.msg.cmd = IPMI_LAN_GET_STAT; 2170 req.msg.data = msg_data; 2171 req.msg.data_len = 2; 2172 2173 rsp = intf->sendrecv(intf, &req); 2174 if (rsp == NULL) { 2175 lprintf(LOG_INFO, "Get LAN Stats command failed"); 2176 return (-1); 2177 } 2178 2179 if (rsp->ccode > 0) { 2180 lprintf(LOG_INFO, "Get LAN Stats command failed: %s", 2181 val2str(rsp->ccode, completion_code_vals)); 2182 return (-1); 2183 } 2184 2185 return rc; 2186 } 2187 2188 static void 2189 print_lan_alert_print_usage(void) 2190 { 2191 lprintf(LOG_NOTICE, 2192 ""); 2193 lprintf(LOG_NOTICE, 2194 "usage: lan alert print [channel number] [alert destination]"); 2195 lprintf(LOG_NOTICE, 2196 ""); 2197 lprintf(LOG_NOTICE, 2198 "Default will print all alerts for the first found LAN channel"); 2199 } 2200 2201 static void 2202 print_lan_alert_set_usage(void) 2203 { 2204 lprintf(LOG_NOTICE, 2205 ""); 2206 lprintf(LOG_NOTICE, 2207 "usage: lan alert set <channel number> <alert destination> <command> <parameter>"); 2208 lprintf(LOG_NOTICE, 2209 ""); 2210 lprintf(LOG_NOTICE, 2211 " Command/parameter options:"); 2212 lprintf(LOG_NOTICE, 2213 ""); 2214 lprintf(LOG_NOTICE, 2215 " ipaddr <x.x.x.x> Set alert IP address"); 2216 lprintf(LOG_NOTICE, 2217 " macaddr <x:x:x:x:x:x> Set alert MAC address"); 2218 lprintf(LOG_NOTICE, 2219 " gateway <default|backup> Set channel gateway to use for alerts"); 2220 lprintf(LOG_NOTICE, 2221 " ack <on|off> Set Alert Acknowledge on or off"); 2222 lprintf(LOG_NOTICE, 2223 " type <pet|oem1|oem2> Set destination type as PET or OEM"); 2224 lprintf(LOG_NOTICE, 2225 " time <seconds> Set ack timeout or unack retry interval"); 2226 lprintf(LOG_NOTICE, 2227 " retry <number> Set number of alert retries"); 2228 lprintf(LOG_NOTICE, 2229 ""); 2230 } 2231 2232 static void 2233 print_lan_set_usage(void) 2234 { 2235 lprintf(LOG_NOTICE, 2236 ""); 2237 lprintf(LOG_NOTICE, 2238 "usage: lan set <channel> <command> <parameter>"); 2239 lprintf(LOG_NOTICE, 2240 ""); 2241 lprintf(LOG_NOTICE, 2242 "LAN set command/parameter options:"); 2243 lprintf(LOG_NOTICE, 2244 " ipaddr <x.x.x.x> Set channel IP address"); 2245 lprintf(LOG_NOTICE, 2246 " netmask <x.x.x.x> Set channel IP netmask"); 2247 lprintf(LOG_NOTICE, 2248 " macaddr <x:x:x:x:x:x> Set channel MAC address"); 2249 lprintf(LOG_NOTICE, 2250 " defgw ipaddr <x.x.x.x> Set default gateway IP address"); 2251 lprintf(LOG_NOTICE, 2252 " defgw macaddr <x:x:x:x:x:x> Set default gateway MAC address"); 2253 lprintf(LOG_NOTICE, 2254 " bakgw ipaddr <x.x.x.x> Set backup gateway IP address"); 2255 lprintf(LOG_NOTICE, 2256 " bakgw macaddr <x:x:x:x:x:x> Set backup gateway MAC address"); 2257 lprintf(LOG_NOTICE, 2258 " password <password> Set session password for this channel"); 2259 lprintf(LOG_NOTICE, 2260 " snmp <community string> Set SNMP public community string"); 2261 lprintf(LOG_NOTICE, 2262 " user Enable default user for this channel"); 2263 lprintf(LOG_NOTICE, 2264 " access <on|off> Enable or disable access to this channel"); 2265 lprintf(LOG_NOTICE, 2266 " alert <on|off> Enable or disable PEF alerting for this channel"); 2267 lprintf(LOG_NOTICE, 2268 " arp respond <on|off> Enable or disable BMC ARP responding"); 2269 lprintf(LOG_NOTICE, 2270 " arp generate <on|off> Enable or disable BMC gratuitous ARP generation"); 2271 lprintf(LOG_NOTICE, 2272 " arp interval <seconds> Set gratuitous ARP generation interval"); 2273 lprintf(LOG_NOTICE, 2274 " vlan id <off|<id>> Disable or enable VLAN and set ID (1-4094)"); 2275 lprintf(LOG_NOTICE, 2276 " vlan priority <priority> Set vlan priority (0-7)"); 2277 lprintf(LOG_NOTICE, 2278 " auth <level> <type,..> Set channel authentication types"); 2279 lprintf(LOG_NOTICE, 2280 " level = CALLBACK, USER, OPERATOR, ADMIN"); 2281 lprintf(LOG_NOTICE, 2282 " type = NONE, MD2, MD5, PASSWORD, OEM"); 2283 lprintf(LOG_NOTICE, 2284 " ipsrc <source> Set IP Address source"); 2285 lprintf(LOG_NOTICE, 2286 " none = unspecified source"); 2287 lprintf(LOG_NOTICE, 2288 " static = address manually configured to be static"); 2289 lprintf(LOG_NOTICE, 2290 " dhcp = address obtained by BMC running DHCP"); 2291 lprintf(LOG_NOTICE, 2292 " bios = address loaded by BIOS or system software"); 2293 lprintf(LOG_NOTICE, 2294 " cipher_privs XXXXXXXXXXXXXXX Set RMCP+ cipher suite privilege levels"); 2295 lprintf(LOG_NOTICE, 2296 " X = Cipher Suite Unused"); 2297 lprintf(LOG_NOTICE, 2298 " c = CALLBACK"); 2299 lprintf(LOG_NOTICE, 2300 " u = USER"); 2301 lprintf(LOG_NOTICE, 2302 " o = OPERATOR"); 2303 lprintf(LOG_NOTICE, 2304 " a = ADMIN"); 2305 lprintf(LOG_NOTICE, 2306 " O = OEM"); 2307 lprintf(LOG_NOTICE, 2308 ""); 2309 lprintf(LOG_NOTICE, 2310 " bad_pass_thresh <thresh_num> <1|0> <reset_interval> <lockout_interval>\n" 2311 " Set bad password threshold"); 2312 } 2313 2314 static void 2315 print_lan_set_access_usage(void) 2316 { 2317 lprintf(LOG_NOTICE, 2318 "lan set access <on|off>"); 2319 } 2320 2321 static void 2322 print_lan_set_arp_usage(void) 2323 { 2324 lprintf(LOG_NOTICE, 2325 "lan set <channel> arp respond <on|off>"); 2326 lprintf(LOG_NOTICE, 2327 "lan set <channel> arp generate <on|off>"); 2328 lprintf(LOG_NOTICE, 2329 "lan set <channel> arp interval <seconds>"); 2330 lprintf(LOG_NOTICE, 2331 ""); 2332 lprintf(LOG_NOTICE, 2333 "example: lan set 7 arp gratuitous off"); 2334 } 2335 2336 static void 2337 print_lan_set_auth_usage(void) 2338 { 2339 lprintf(LOG_NOTICE, 2340 "lan set <channel> auth <level> <type,type,...>"); 2341 lprintf(LOG_NOTICE, 2342 " level = CALLBACK, USER, OPERATOR, ADMIN"); 2343 lprintf(LOG_NOTICE, 2344 " types = NONE, MD2, MD5, PASSWORD, OEM"); 2345 lprintf(LOG_NOTICE, 2346 "example: lan set 7 auth ADMIN PASSWORD,MD5"); 2347 } 2348 2349 static void 2350 print_lan_set_bakgw_usage(void) 2351 { 2352 lprintf(LOG_NOTICE, 2353 "LAN set backup gateway commands: ipaddr, macaddr"); 2354 } 2355 2356 static void 2357 print_lan_set_cipher_privs_usage(void) 2358 { 2359 lprintf(LOG_NOTICE, 2360 "lan set <channel> cipher_privs XXXXXXXXXXXXXXX"); 2361 lprintf(LOG_NOTICE, 2362 " X = Cipher Suite Unused"); 2363 lprintf(LOG_NOTICE, 2364 " c = CALLBACK"); 2365 lprintf(LOG_NOTICE, 2366 " u = USER"); 2367 lprintf(LOG_NOTICE, 2368 " o = OPERATOR"); 2369 lprintf(LOG_NOTICE, 2370 " a = ADMIN"); 2371 lprintf(LOG_NOTICE, 2372 " O = OEM"); 2373 lprintf(LOG_NOTICE, 2374 ""); 2375 } 2376 2377 static void 2378 print_lan_set_defgw_usage(void) 2379 { 2380 lprintf(LOG_NOTICE, 2381 "LAN set default gateway Commands: ipaddr, macaddr"); 2382 } 2383 2384 static void 2385 print_lan_set_ipsrc_usage(void) 2386 { 2387 lprintf(LOG_NOTICE, 2388 "lan set <channel> ipsrc <source>"); 2389 lprintf(LOG_NOTICE, 2390 " none = unspecified"); 2391 lprintf(LOG_NOTICE, 2392 " static = static address (manually configured)"); 2393 lprintf(LOG_NOTICE, 2394 " dhcp = address obtained by BMC running DHCP"); 2395 lprintf(LOG_NOTICE, 2396 " bios = address loaded by BIOS or system software"); 2397 } 2398 2399 static void 2400 print_lan_set_snmp_usage(void) 2401 { 2402 lprintf(LOG_NOTICE, 2403 "lan set <channel> snmp <community string>"); 2404 } 2405 2406 static void 2407 print_lan_set_vlan_usage(void) 2408 { 2409 lprintf(LOG_NOTICE, 2410 "lan set <channel> vlan id <id>"); 2411 lprintf(LOG_NOTICE, 2412 "lan set <channel> vlan id off"); 2413 lprintf(LOG_NOTICE, 2414 "lan set <channel> vlan priority <priority>"); 2415 } 2416 2417 /* 2418 * print_lan_usage 2419 */ 2420 static void 2421 print_lan_usage(void) 2422 { 2423 lprintf(LOG_NOTICE, 2424 "LAN Commands:"); 2425 lprintf(LOG_NOTICE, 2426 " print [<channel number>]"); 2427 lprintf(LOG_NOTICE, 2428 " set <channel number> <command> <parameter>"); 2429 lprintf(LOG_NOTICE, 2430 " alert print <channel number> <alert destination>"); 2431 lprintf(LOG_NOTICE, 2432 " alert set <channel number> <alert destination> <command> <parameter>"); 2433 lprintf(LOG_NOTICE, 2434 " stats get [<channel number>]"); 2435 lprintf(LOG_NOTICE, 2436 " stats clear [<channel number>]"); 2437 } 2438 2439 2440 int 2441 ipmi_lanp_main(struct ipmi_intf * intf, int argc, char ** argv) 2442 { 2443 int rc = 0; 2444 uint8_t chan = 0; 2445 2446 if (argc == 0) { 2447 print_lan_usage(); 2448 return (-1); 2449 } else if (strncmp(argv[0], "help", 4) == 0) { 2450 print_lan_usage(); 2451 return 0; 2452 } 2453 2454 chan = find_lan_channel(intf, 1); 2455 2456 if (strncmp(argv[0], "printconf", 9) == 0 || 2457 strncmp(argv[0], "print", 5) == 0) 2458 { 2459 if (argc > 2) { 2460 print_lan_usage(); 2461 return (-1); 2462 } else if (argc == 2) { 2463 if (str2uchar(argv[1], &chan) != 0) { 2464 lprintf(LOG_ERR, "Invalid channel: %s", argv[1]); 2465 return (-1); 2466 } 2467 } else { 2468 chan = find_lan_channel(intf, 1); 2469 } 2470 if (!is_lan_channel(intf, chan)) { 2471 lprintf(LOG_ERR, "Invalid channel: %d", chan); 2472 return (-1); 2473 } 2474 rc = ipmi_lan_print(intf, chan); 2475 } else if (strncmp(argv[0], "set", 3) == 0) { 2476 rc = ipmi_lan_set(intf, argc-1, &(argv[1])); 2477 } else if (strncmp(argv[0], "alert", 5) == 0) { 2478 rc = ipmi_lan_alert(intf, argc-1, &(argv[1])); 2479 } else if (strncmp(argv[0], "stats", 5) == 0) { 2480 if (argc < 2) { 2481 print_lan_usage(); 2482 return (-1); 2483 } else if (argc == 3) { 2484 if (str2uchar(argv[2], &chan) != 0) { 2485 lprintf(LOG_ERR, "Invalid channel: %s", argv[2]); 2486 return (-1); 2487 } 2488 } else { 2489 chan = find_lan_channel(intf, 1); 2490 } 2491 if (!is_lan_channel(intf, chan)) { 2492 lprintf(LOG_ERR, "Invalid channel: %d", chan); 2493 return (-1); 2494 } 2495 if (strncmp(argv[1], "get", 3) == 0) { 2496 rc = ipmi_lan_stats_get(intf, chan); 2497 } else if (strncmp(argv[1], "clear", 5) == 0) { 2498 rc = ipmi_lan_stats_clear(intf, chan); 2499 } else { 2500 print_lan_usage(); 2501 return (-1); 2502 } 2503 } else { 2504 lprintf(LOG_NOTICE, "Invalid LAN command: %s", argv[0]); 2505 return (-1); 2506 } 2507 return rc; 2508 } 2509