/* * Copyright (c) 2003, 2004 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #define _SVID_SOURCE || _BSD_SOURCE || _XOPEN_SOURCE >= 500 || \ _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED || \ /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809L #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H # include #endif #define EXEC_BUF_SIZE 2048 #define EXEC_ARG_SIZE 64 #define MAX_PORT 65535 extern const struct valstr ipmi_privlvl_vals[]; extern const struct valstr ipmi_authtype_session_vals[]; #ifdef HAVE_READLINE /* avoid warnings errors due to non-ANSI type declarations in readline.h */ #define _FUNCTION_DEF #define USE_VARARGS #define PREFER_STDARG #include #include #define RL_PROMPT "ipmitool> " #define RL_TIMEOUT 30 static struct ipmi_intf * shell_intf; /* This function attempts to keep lan sessions active * so they do not time out waiting for user input. The * readline timeout is set to 1 second but lan session * timeout is ~60 seconds. */ static int rl_event_keepalive(void) { static int internal_timer = 0; if (shell_intf == NULL) return -1; if (shell_intf->keepalive == NULL) return 0; #if defined (RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0402 if (internal_timer++ < RL_TIMEOUT) #else /* In readline < 4.2 keyboard timeout hardcoded to 0.1 second */ if (internal_timer++ < RL_TIMEOUT * 10) #endif return 0; internal_timer = 0; shell_intf->keepalive(shell_intf); return 0; } int ipmi_shell_main(struct ipmi_intf * intf, int argc, char ** argv) { char *ptr, *pbuf, **ap, *__argv[EXEC_ARG_SIZE]; int __argc, rc=0; rl_readline_name = "ipmitool"; /* this essentially disables command completion * until its implemented right, otherwise we get * the current directory contents... */ rl_bind_key('\t', rl_insert); if (intf->keepalive) { /* hook to keep lan sessions active */ shell_intf = intf; rl_event_hook = rl_event_keepalive; #if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0402 /* There is a bug in readline 4.2 and later (at least on FreeBSD and NetBSD): * timeout equal or greater than 1 second causes an infinite loop. */ rl_set_keyboard_input_timeout(1000 * 1000 - 1); #endif } while ((pbuf = (char *)readline(RL_PROMPT)) != NULL) { if (strlen(pbuf) == 0) { free(pbuf); pbuf = NULL; continue; } if (strncmp(pbuf, "quit", 4) == 0 || strncmp(pbuf, "exit", 4) == 0) { free(pbuf); pbuf = NULL; return 0; } if (strncmp(pbuf, "help", 4) == 0 || strncmp(pbuf, "?", 1) == 0) { ipmi_cmd_print(intf->cmdlist); free(pbuf); pbuf = NULL; continue; } /* for the all-important up arrow :) */ add_history(pbuf); /* change "" and '' with spaces in the middle to ~ */ ptr = pbuf; while (*ptr != '\0') { if (*ptr == '"') { ptr++; while (*ptr != '"' && *ptr != '\0') { if (isspace((int)*ptr)) *ptr = '~'; ptr++; } } if (*ptr == '\'') { ptr++; while (*ptr != '\'' && *ptr != '\0') { if (isspace((int)*ptr)) *ptr = '~'; ptr++; } } ptr++; } __argc = 0; ap = __argv; for (*ap = strtok(pbuf, " \t"); *ap != NULL; *ap = strtok(NULL, " \t")) { __argc++; ptr = *ap; if (*ptr == '\'') { memmove(ptr, ptr+1, strlen(ptr)); while (*ptr != '\'' && *ptr != '\0') { if (*ptr == '~') *ptr = ' '; ptr++; } *ptr = '\0'; } if (*ptr == '"') { memmove(ptr, ptr+1, strlen(ptr)); while (*ptr != '"' && *ptr != '\0') { if (*ptr == '~') *ptr = ' '; ptr++; } *ptr = '\0'; } if (**ap != '\0') { if (++ap >= &__argv[EXEC_ARG_SIZE]) break; } } if (__argc && __argv[0]) rc = ipmi_cmd_run(intf, __argv[0], __argc-1, &(__argv[1])); free(pbuf); pbuf = NULL; } printf("\n"); return rc; } #else /* HAVE_READLINE */ int ipmi_shell_main(struct ipmi_intf * intf, int argc, char ** argv) { lprintf(LOG_ERR, "Compiled without readline, shell is disabled"); return -1; } #endif /* HAVE_READLINE */ int ipmi_echo_main(struct ipmi_intf * intf, int argc, char ** argv) { int i; for (i=0; i \n"); lprintf(LOG_NOTICE, "Options are:"); lprintf(LOG_NOTICE, " hostname Session hostname"); lprintf(LOG_NOTICE, " username Session username"); lprintf(LOG_NOTICE, " password Session password"); lprintf(LOG_NOTICE, " privlvl Session privilege level force"); lprintf(LOG_NOTICE, " authtype Authentication type force"); lprintf(LOG_NOTICE, " localaddr Local IPMB address"); lprintf(LOG_NOTICE, " targetaddr Remote target IPMB address"); lprintf(LOG_NOTICE, " port Remote RMCP port"); lprintf(LOG_NOTICE, " csv [level] enable output in comma separated format"); lprintf(LOG_NOTICE, " verbose [level] Verbose level"); lprintf(LOG_NOTICE, ""); } int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv) { if (argc == 0 || strncmp(argv[0], "help", 4) == 0) { ipmi_set_usage(); return -1; } /* these options can have no arguments */ if (strncmp(argv[0], "verbose", 7) == 0) { if (argc > 1) { if (str2int(argv[1], &verbose) != 0) { lprintf(LOG_ERR, "Given verbose '%s' argument is invalid.", argv[1]); return (-1); } } else { verbose = verbose + 1; } return 0; } if (strncmp(argv[0], "csv", 3) == 0) { if (argc > 1) { if (str2int(argv[1], &csv_output) != 0) { lprintf(LOG_ERR, "Given csv '%s' argument is invalid.", argv[1]); return (-1); } } else { csv_output = 1; } return 0; } /* the rest need an argument */ if (argc == 1) { ipmi_set_usage(); return -1; } if (strncmp(argv[0], "host", 4) == 0 || strncmp(argv[0], "hostname", 8) == 0) { ipmi_intf_session_set_hostname(intf, argv[1]); if (intf->session == NULL) { lprintf(LOG_ERR, "Failed to set session hostname."); return (-1); } printf("Set session hostname to %s\n", intf->ssn_params.hostname); } else if (strncmp(argv[0], "user", 4) == 0 || strncmp(argv[0], "username", 8) == 0) { ipmi_intf_session_set_username(intf, argv[1]); if (intf->session == NULL) { lprintf(LOG_ERR, "Failed to set session username."); return (-1); } printf("Set session username to %s\n", intf->ssn_params.username); } else if (strncmp(argv[0], "pass", 4) == 0 || strncmp(argv[0], "password", 8) == 0) { ipmi_intf_session_set_password(intf, argv[1]); if (intf->session == NULL) { lprintf(LOG_ERR, "Failed to set session password."); return (-1); } printf("Set session password\n"); } else if (strncmp(argv[0], "authtype", 8) == 0) { int authtype; authtype = str2val(argv[1], ipmi_authtype_session_vals); if (authtype == 0xFF) { lprintf(LOG_ERR, "Invalid authtype: %s", argv[1]); return (-1); } ipmi_intf_session_set_authtype(intf, authtype); if (intf->session == NULL) { lprintf(LOG_ERR, "Failed to set session authtype."); return (-1); } printf("Set session authtype to %s\n", val2str(intf->ssn_params.authtype_set, ipmi_authtype_session_vals)); } else if (strncmp(argv[0], "privlvl", 7) == 0) { int privlvl; privlvl = str2val(argv[1], ipmi_privlvl_vals); if (privlvl == 0xFF) { lprintf(LOG_ERR, "Invalid privilege level: %s", argv[1]); return (-1); } ipmi_intf_session_set_privlvl(intf, privlvl); if (intf->session == NULL) { lprintf(LOG_ERR, "Failed to set session privilege level."); return (-1); } printf("Set session privilege level to %s\n", val2str(intf->ssn_params.privlvl, ipmi_privlvl_vals)); } else if (strncmp(argv[0], "port", 4) == 0) { int port = 0; if (str2int(argv[1], &port) != 0 || port > MAX_PORT) { lprintf(LOG_ERR, "Given port '%s' is invalid.", argv[1]); return (-1); } ipmi_intf_session_set_port(intf, port); if (intf->session == NULL) { lprintf(LOG_ERR, "Failed to set session port."); return (-1); } printf("Set session port to %d\n", intf->ssn_params.port); } else if (strncmp(argv[0], "localaddr", 9) == 0) { uint8_t my_addr = 0; if (str2uchar(argv[1], &my_addr) != 0) { lprintf(LOG_ERR, "Given localaddr '%s' is invalid.", argv[1]); return (-1); } intf->my_addr = my_addr; printf("Set local IPMB address to 0x%02x\n", intf->my_addr); } else if (strncmp(argv[0], "targetaddr", 10) == 0) { uint8_t target_addr = 0; if (str2uchar(argv[1], &target_addr) != 0) { lprintf(LOG_ERR, "Given targetaddr '%s' is invalid.", argv[1]); return (-1); } intf->target_addr = target_addr; printf("Set remote IPMB address to 0x%02x\n", intf->target_addr); } else { ipmi_set_usage(); return -1; } return 0; } int ipmi_exec_main(struct ipmi_intf * intf, int argc, char ** argv) { FILE * fp; char buf[EXEC_BUF_SIZE]; char * ptr, * tok, * ret, * tmp; int __argc, i, r; char * __argv[EXEC_ARG_SIZE]; int rc=0; if (argc < 1) { lprintf(LOG_ERR, "Usage: exec "); return -1; } fp = ipmi_open_file_read(argv[0]); if (fp == NULL) return -1; while (feof(fp) == 0) { ret = fgets(buf, EXEC_BUF_SIZE, fp); if (ret == NULL) continue; /* clip off optional comment tail indicated by # */ ptr = strchr(buf, '#'); if (ptr) *ptr = '\0'; else ptr = buf + strlen(buf); /* change "" and '' with spaces in the middle to ~ */ ptr = buf; while (*ptr != '\0') { if (*ptr == '"') { ptr++; while (*ptr != '"' && *ptr != '\0') { if (isspace((int)*ptr)) *ptr = '~'; ptr++; } } if (*ptr == '\'') { ptr++; while (*ptr != '\'' && *ptr != '\0') { if (isspace((int)*ptr)) *ptr = '~'; ptr++; } } ptr++; } /* clip off trailing and leading whitespace */ ptr--; while (isspace((int)*ptr) && ptr >= buf) *ptr-- = '\0'; ptr = buf; while (isspace((int)*ptr)) ptr++; if (strlen(ptr) == 0) continue; /* parse it and make argument list */ __argc = 0; for (tok = strtok(ptr, " "); tok != NULL; tok = strtok(NULL, " ")) { if (__argc < EXEC_ARG_SIZE) { __argv[__argc++] = strdup(tok); if (__argv[__argc-1] == NULL) { lprintf(LOG_ERR, "ipmitool: malloc failure"); if (fp) { fclose(fp); fp = NULL; } return -1; } tmp = __argv[__argc-1]; if (*tmp == '\'') { memmove(tmp, tmp+1, strlen(tmp)); while (*tmp != '\'' && *tmp != '\0') { if (*tmp == '~') *tmp = ' '; tmp++; } *tmp = '\0'; } if (*tmp == '"') { memmove(tmp, tmp+1, strlen(tmp)); while (*tmp != '"' && *tmp != '\0') { if (*tmp == '~') *tmp = ' '; tmp++; } *tmp = '\0'; } } } /* now run the command, save the result if not successful */ r = ipmi_cmd_run(intf, __argv[0], __argc-1, &(__argv[1])); if (r != 0) rc = r; /* free argument list */ for (i=0; i<__argc; i++) { if (__argv[i] != NULL) { free(__argv[i]); __argv[i] = NULL; } } } fclose(fp); return rc; }