diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2014-07-23 15:03:00 +0200 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2014-07-23 15:03:00 +0200 |
commit | b32d92e890caac903491116e9d817aa780c0323b (patch) | |
tree | 5a135c37eaa9ac94772819a28ce5beedd18e5c4a /src/plugins/free/free.c | |
parent | c3445516ecd58e97de483cf4b7fafcc1104890d7 (diff) |
Imported Upstream version 1.8.14upstream/1.8.14
Diffstat (limited to 'src/plugins/free/free.c')
-rw-r--r-- | src/plugins/free/free.c | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/src/plugins/free/free.c b/src/plugins/free/free.c new file mode 100644 index 0000000..f89925d --- /dev/null +++ b/src/plugins/free/free.c @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2003 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. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ + +#if defined(HAVE_CONFIG_H) +# include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +#include <ipmitool/ipmi.h> +#include <ipmitool/ipmi_intf.h> + +#include <freeipmi/freeipmi.h> +#if IPMI_INTF_FREE_0_3_0 || IPMI_INTF_FREE_0_4_0 || IPMI_INTF_FREE_0_5_0 +#include <freeipmi/udm/ipmi-udm.h> +#endif + +#if IPMI_INTF_FREE_0_6_0 +ipmi_ctx_t dev = NULL; +#else /* !IPMI_INTF_FREE_0_6_0 */ +ipmi_device_t dev = NULL; +#endif /* !IPMI_INTF_FREE_0_6_0 */ + +extern int verbose; + +static int ipmi_free_open(struct ipmi_intf * intf) +{ + int kcs_ret = -1, ssif_ret = -1; + + if (getuid() != 0) { + fprintf(stderr, "Permission denied, must be root\n"); + return -1; + } + +#if IPMI_INTF_FREE_0_3_0 + if (!(dev = ipmi_open_inband (IPMI_DEVICE_KCS, + 0, + 0, + 0, + NULL, + IPMI_FLAGS_DEFAULT))) { + if (!(dev = ipmi_open_inband (IPMI_DEVICE_SSIF, + 0, + 0, + 0, + NULL, + IPMI_FLAGS_DEFAULT))) { + perror("ipmi_open_inband()"); + goto cleanup; + } + } +#elif IPMI_INTF_FREE_0_4_0 + if (!(dev = ipmi_device_create())) { + perror("ipmi_device_create"); + goto cleanup; + } + if (ipmi_open_inband (dev, + IPMI_DEVICE_KCS, + 0, + 0, + 0, + NULL, + IPMI_FLAGS_DEFAULT) < 0) { + if (ipmi_open_inband (dev, + IPMI_DEVICE_SSIF, + 0, + 0, + 0, + NULL, + IPMI_FLAGS_DEFAULT) < 0) { + fprintf(stderr, + "ipmi_open_inband(): %s\n", + ipmi_device_strerror(ipmi_device_errnum(dev))); + goto cleanup; + } + } +#elif IPMI_INTF_FREE_0_5_0 + if (!(dev = ipmi_device_create())) { + perror("ipmi_device_create"); + goto cleanup; + } + if (ipmi_open_inband (dev, + IPMI_DEVICE_KCS, + 0, + 0, + 0, + NULL, + 0, + IPMI_FLAGS_DEFAULT) < 0) { + if (ipmi_open_inband (dev, + IPMI_DEVICE_SSIF, + 0, + 0, + 0, + NULL, + 0, + IPMI_FLAGS_DEFAULT) < 0) { + fprintf(stderr, + "ipmi_open_inband(): %s\n", + ipmi_device_strerror(ipmi_device_errnum(dev))); + goto cleanup; + } + } +#elif IPMI_INTF_FREE_0_6_0 + if (!(dev = ipmi_ctx_create())) { + perror("ipmi_ctx_create"); + goto cleanup; + } + if (ipmi_ctx_open_inband (dev, + IPMI_DEVICE_KCS, + 0, + 0, + 0, + NULL, + 0, + IPMI_FLAGS_DEFAULT) < 0) { + if (ipmi_ctx_open_inband (dev, + IPMI_DEVICE_SSIF, + 0, + 0, + 0, + NULL, + 0, + IPMI_FLAGS_DEFAULT) < 0) { + fprintf(stderr, + "ipmi_open_inband(): %s\n", + ipmi_ctx_strerror(ipmi_ctx_errnum(dev))); + goto cleanup; + } + } +#endif + + intf->opened = 1; + intf->manufacturer_id = ipmi_get_oem(intf); + return 0; + cleanup: + if (dev) { +#if IPMI_INTF_FREE_0_3_0 + ipmi_close_device(dev); +#elif IPMI_INTF_FREE_0_4_0 || IPMI_INTF_FREE_0_5_0 + ipmi_close_device(dev); + ipmi_device_destroy(dev); +#elif IPMI_INTF_FREE_0_6_0 + ipmi_ctx_close(dev); + ipmi_ctx_destroy(dev); +#endif + } + return -1; +} + +static void ipmi_free_close(struct ipmi_intf * intf) +{ + if (dev) { +#if IPMI_INTF_FREE_0_3_0 + ipmi_close_device(dev); +#elif IPMI_INTF_FREE_0_4_0 || IPMI_INTF_FREE_0_5_0 + ipmi_close_device(dev); + ipmi_device_destroy(dev); +#elif IPMI_INTF_FREE_0_6_0 + ipmi_ctx_close(dev); + ipmi_ctx_destroy(dev); +#endif + } + intf->opened = 0; + intf->manufacturer_id = IPMI_OEM_UNKNOWN; +} + +static struct ipmi_rs * ipmi_free_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) +{ + u_int8_t lun = req->msg.lun; + u_int8_t cmd = req->msg.cmd; + u_int8_t netfn = req->msg.netfn; + u_int8_t rq_buf[IPMI_BUF_SIZE]; + u_int8_t rs_buf[IPMI_BUF_SIZE]; + u_int32_t rs_buf_len = IPMI_BUF_SIZE; + int32_t rs_len; + + static struct ipmi_rs rsp; + + /* achu: FreeIPMI requests have the cmd as the first byte of + * the data. Responses have cmd as the first byte and + * completion code as the second byte. This differs from some + * other APIs, so it must be compensated for within the ipmitool + * interface. + */ + + if (!intf || !req) + return NULL; + + if (!intf->opened && intf->open && intf->open(intf) < 0) + return NULL; + + if (req->msg.data_len > IPMI_BUF_SIZE) + return NULL; + + memset(rq_buf, '\0', IPMI_BUF_SIZE); + memset(rs_buf, '\0', IPMI_BUF_SIZE); + memcpy(rq_buf, &cmd, 1); + + if (req->msg.data) + memcpy(rq_buf + 1, req->msg.data, req->msg.data_len); + + if (intf->target_addr != 0 + && intf->target_addr != IPMI_BMC_SLAVE_ADDR) { +#if IPMI_INTF_FREE_BRIDGING + if ((rs_len = ipmi_cmd_raw_ipmb(dev, + intf->target_channel, + intf->target_addr, + lun, + netfn, + rq_buf, + req->msg.data_len + 1, + rs_buf, + rs_buf_len)) < 0) { + if (verbose > 3) + fprintf(stderr, + "ipmi_cmd_raw_ipmb: %s\n", + ipmi_ctx_strerror(ipmi_ctx_errnum(dev))); + /* Compared to FreeIPMI, user is expected to input + * the target channel on the command line, it is not automatically + * discovered. So that is the likely cause of an error. + * + * Instead of returning an error, return a bad response so output + * of ipmitool commands looks like other interfaces + */ + rs_len = 2; + rs_buf[0] = 0; + rs_buf[1] = 0xC1; /* invalid command */ + } +#else /* !IPMI_INTF_FREE_BRIDGING */ + if (verbose > 3) + fprintf(stderr, "sensor bridging not supported in this driver version"); + /* instead of returning an error, return a bad response so output + * of ipmitool commands looks like other interfaces + */ + rs_len = 2; + rs_buf[0] = 0; + rs_buf[1] = 0xC1; /* invalid command */ +#endif /* !IPMI_INTF_FREE_BRIDGING */ + } + else { + if ((rs_len = ipmi_cmd_raw(dev, + lun, + netfn, + rq_buf, + req->msg.data_len + 1, + rs_buf, + rs_buf_len)) < 0) { +#if IPMI_INTF_FREE_0_3_0 + perror("ipmi_cmd_raw"); +#elif IPMI_INTF_FREE_0_4_0 || IPMI_INTF_FREE_0_5_0 + fprintf(stderr, + "ipmi_cmd_raw: %s\n", + ipmi_device_strerror(ipmi_device_errnum(dev))); +#elif IPMI_INTF_FREE_0_6_0 + fprintf(stderr, + "ipmi_cmd_raw: %s\n", + ipmi_ctx_strerror(ipmi_ctx_errnum(dev))); +#endif + return NULL; + } + } + + memset(&rsp, 0, sizeof(struct ipmi_rs)); + rsp.ccode = (unsigned char)rs_buf[1]; + rsp.data_len = (int)rs_len - 2; + + if (!rsp.ccode && rsp.data_len) + memcpy(rsp.data, rs_buf + 2, rsp.data_len); + + return &rsp; +} + +struct ipmi_intf ipmi_free_intf = { + name: "free", + desc: "FreeIPMI IPMI Interface", + open: ipmi_free_open, + close: ipmi_free_close, + sendrecv: ipmi_free_send_cmd, + target_addr: IPMI_BMC_SLAVE_ADDR, +}; + |