Blame src/plugins/free/free.c

Packit d14fb6
/*
Packit d14fb6
 * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
Packit d14fb6
 * 
Packit d14fb6
 * Redistribution and use in source and binary forms, with or without
Packit d14fb6
 * modification, are permitted provided that the following conditions
Packit d14fb6
 * are met:
Packit d14fb6
 * 
Packit d14fb6
 * Redistribution of source code must retain the above copyright
Packit d14fb6
 * notice, this list of conditions and the following disclaimer.
Packit d14fb6
 * 
Packit d14fb6
 * Redistribution in binary form must reproduce the above copyright
Packit d14fb6
 * notice, this list of conditions and the following disclaimer in the
Packit d14fb6
 * documentation and/or other materials provided with the distribution.
Packit d14fb6
 * 
Packit d14fb6
 * Neither the name of Sun Microsystems, Inc. or the names of
Packit d14fb6
 * contributors may be used to endorse or promote products derived
Packit d14fb6
 * from this software without specific prior written permission.
Packit d14fb6
 * 
Packit d14fb6
 * This software is provided "AS IS," without a warranty of any kind.
Packit d14fb6
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
Packit d14fb6
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
Packit d14fb6
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
Packit d14fb6
 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
Packit d14fb6
 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
Packit d14fb6
 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
Packit d14fb6
 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
Packit d14fb6
 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
Packit d14fb6
 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
Packit d14fb6
 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
Packit d14fb6
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
Packit d14fb6
 * 
Packit d14fb6
 * You acknowledge that this software is not designed or intended for use
Packit d14fb6
 * in the design, construction, operation or maintenance of any nuclear
Packit d14fb6
 * facility.
Packit d14fb6
 */
Packit d14fb6
Packit d14fb6
#if defined(HAVE_CONFIG_H)
Packit d14fb6
# include <config.h>
Packit d14fb6
#endif
Packit d14fb6
Packit d14fb6
#include <stdio.h>
Packit d14fb6
#include <stdlib.h>
Packit d14fb6
#include <string.h>
Packit d14fb6
#include <sys/types.h>
Packit d14fb6
Packit d14fb6
#include <ipmitool/ipmi.h>
Packit d14fb6
#include <ipmitool/ipmi_intf.h>
Packit d14fb6
Packit d14fb6
#include <freeipmi/freeipmi.h>
Packit d14fb6
#if IPMI_INTF_FREE_0_3_0 || IPMI_INTF_FREE_0_4_0 || IPMI_INTF_FREE_0_5_0
Packit d14fb6
#include <freeipmi/udm/ipmi-udm.h>
Packit d14fb6
#endif
Packit d14fb6
Packit d14fb6
#if IPMI_INTF_FREE_0_6_0
Packit d14fb6
ipmi_ctx_t dev = NULL;
Packit d14fb6
#else  /* !IPMI_INTF_FREE_0_6_0 */
Packit d14fb6
ipmi_device_t dev = NULL;
Packit d14fb6
#endif  /* !IPMI_INTF_FREE_0_6_0 */
Packit d14fb6
Packit d14fb6
extern int verbose;
Packit d14fb6
Packit d14fb6
static int ipmi_free_open(struct ipmi_intf * intf)
Packit d14fb6
{
Packit d14fb6
        int kcs_ret = -1, ssif_ret = -1;
Packit d14fb6
Packit d14fb6
        if (getuid() != 0) {
Packit d14fb6
                fprintf(stderr, "Permission denied, must be root\n");
Packit d14fb6
                return -1;
Packit d14fb6
        }
Packit d14fb6
Packit d14fb6
#if IPMI_INTF_FREE_0_3_0
Packit d14fb6
        if (!(dev = ipmi_open_inband (IPMI_DEVICE_KCS,
Packit d14fb6
                                      0,
Packit d14fb6
                                      0,
Packit d14fb6
                                      0,
Packit d14fb6
                                      NULL,
Packit d14fb6
                                      IPMI_FLAGS_DEFAULT))) {
Packit d14fb6
                if (!(dev = ipmi_open_inband (IPMI_DEVICE_SSIF,
Packit d14fb6
                                              0,
Packit d14fb6
                                              0,
Packit d14fb6
                                              0,
Packit d14fb6
                                              NULL,
Packit d14fb6
                                              IPMI_FLAGS_DEFAULT))) {
Packit d14fb6
                        perror("ipmi_open_inband()");
Packit d14fb6
                        goto cleanup;
Packit d14fb6
                }
Packit d14fb6
        }
Packit d14fb6
#elif IPMI_INTF_FREE_0_4_0
Packit d14fb6
        if (!(dev = ipmi_device_create())) {
Packit d14fb6
                perror("ipmi_device_create");
Packit d14fb6
                goto cleanup;
Packit d14fb6
        }
Packit d14fb6
        if (ipmi_open_inband (dev,
Packit d14fb6
                              IPMI_DEVICE_KCS,
Packit d14fb6
                              0,
Packit d14fb6
                              0,
Packit d14fb6
                              0,
Packit d14fb6
                              NULL,
Packit d14fb6
                              IPMI_FLAGS_DEFAULT) < 0) {
Packit d14fb6
                if (ipmi_open_inband (dev,
Packit d14fb6
                                      IPMI_DEVICE_SSIF,
Packit d14fb6
                                      0,
Packit d14fb6
                                      0,
Packit d14fb6
                                      0,
Packit d14fb6
                                      NULL,
Packit d14fb6
                                      IPMI_FLAGS_DEFAULT) < 0) {
Packit d14fb6
                       fprintf(stderr, 
Packit d14fb6
                               "ipmi_open_inband(): %s\n",
Packit d14fb6
                               ipmi_device_strerror(ipmi_device_errnum(dev)));
Packit d14fb6
                       goto cleanup;
Packit d14fb6
                }
Packit d14fb6
        }
Packit d14fb6
#elif IPMI_INTF_FREE_0_5_0
Packit d14fb6
        if (!(dev = ipmi_device_create())) {
Packit d14fb6
                perror("ipmi_device_create");
Packit d14fb6
                goto cleanup;
Packit d14fb6
        }
Packit d14fb6
        if (ipmi_open_inband (dev,
Packit d14fb6
                              IPMI_DEVICE_KCS,
Packit d14fb6
                              0,
Packit d14fb6
                              0,
Packit d14fb6
                              0,
Packit d14fb6
                              NULL,
Packit d14fb6
                              0,
Packit d14fb6
                              IPMI_FLAGS_DEFAULT) < 0) {
Packit d14fb6
                if (ipmi_open_inband (dev,
Packit d14fb6
                                      IPMI_DEVICE_SSIF,
Packit d14fb6
                                      0,
Packit d14fb6
                                      0,
Packit d14fb6
                                      0,
Packit d14fb6
                                      NULL,
Packit d14fb6
                                      0,
Packit d14fb6
                                      IPMI_FLAGS_DEFAULT) < 0) {
Packit d14fb6
                       fprintf(stderr, 
Packit d14fb6
                               "ipmi_open_inband(): %s\n",
Packit d14fb6
                               ipmi_device_strerror(ipmi_device_errnum(dev)));
Packit d14fb6
                       goto cleanup;
Packit d14fb6
                }
Packit d14fb6
        }
Packit d14fb6
#elif IPMI_INTF_FREE_0_6_0
Packit d14fb6
        if (!(dev = ipmi_ctx_create())) {
Packit d14fb6
                perror("ipmi_ctx_create");
Packit d14fb6
                goto cleanup;
Packit d14fb6
        }
Packit d14fb6
        if (ipmi_ctx_open_inband (dev,
Packit d14fb6
                                  IPMI_DEVICE_KCS,
Packit d14fb6
                                  0,
Packit d14fb6
                                  0,
Packit d14fb6
                                  0,
Packit d14fb6
                                  NULL,
Packit d14fb6
                                  0,
Packit d14fb6
                                  IPMI_FLAGS_DEFAULT) < 0) {
Packit d14fb6
                if (ipmi_ctx_open_inband (dev,
Packit d14fb6
                                          IPMI_DEVICE_SSIF,
Packit d14fb6
                                          0,
Packit d14fb6
                                          0,
Packit d14fb6
                                          0,
Packit d14fb6
                                          NULL,
Packit d14fb6
                                          0,
Packit d14fb6
                                          IPMI_FLAGS_DEFAULT) < 0) {
Packit d14fb6
                       fprintf(stderr, 
Packit d14fb6
                               "ipmi_open_inband(): %s\n",
Packit d14fb6
                               ipmi_ctx_strerror(ipmi_ctx_errnum(dev)));
Packit d14fb6
                       goto cleanup;
Packit d14fb6
                }
Packit d14fb6
        }
Packit d14fb6
#endif
Packit d14fb6
Packit d14fb6
	intf->opened = 1;
Packit d14fb6
	intf->manufacturer_id = ipmi_get_oem(intf);
Packit d14fb6
	return 0;
Packit d14fb6
 cleanup:
Packit d14fb6
        if (dev) {
Packit d14fb6
#if IPMI_INTF_FREE_0_3_0
Packit d14fb6
                ipmi_close_device(dev);
Packit d14fb6
#elif IPMI_INTF_FREE_0_4_0 || IPMI_INTF_FREE_0_5_0
Packit d14fb6
                ipmi_close_device(dev);
Packit d14fb6
                ipmi_device_destroy(dev);
Packit d14fb6
#elif IPMI_INTF_FREE_0_6_0
Packit d14fb6
                ipmi_ctx_close(dev);
Packit d14fb6
                ipmi_ctx_destroy(dev);
Packit d14fb6
#endif
Packit d14fb6
        }
Packit d14fb6
        return -1;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
static void ipmi_free_close(struct ipmi_intf * intf)
Packit d14fb6
{
Packit d14fb6
        if (dev) {
Packit d14fb6
#if IPMI_INTF_FREE_0_3_0
Packit d14fb6
                ipmi_close_device(dev);
Packit d14fb6
#elif IPMI_INTF_FREE_0_4_0 || IPMI_INTF_FREE_0_5_0
Packit d14fb6
                ipmi_close_device(dev);
Packit d14fb6
                ipmi_device_destroy(dev);
Packit d14fb6
#elif IPMI_INTF_FREE_0_6_0
Packit d14fb6
                ipmi_ctx_close(dev);
Packit d14fb6
                ipmi_ctx_destroy(dev);
Packit d14fb6
#endif
Packit d14fb6
        }
Packit d14fb6
	intf->opened = 0;
Packit d14fb6
	intf->manufacturer_id = IPMI_OEM_UNKNOWN;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
static struct ipmi_rs * ipmi_free_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
Packit d14fb6
{
Packit d14fb6
        uint8_t lun = req->msg.lun;
Packit d14fb6
        uint8_t cmd = req->msg.cmd;
Packit d14fb6
        uint8_t netfn = req->msg.netfn;
Packit d14fb6
        uint8_t rq_buf[IPMI_BUF_SIZE];
Packit d14fb6
        uint8_t rs_buf[IPMI_BUF_SIZE];
Packit d14fb6
        uint32_t rs_buf_len = IPMI_BUF_SIZE;
Packit d14fb6
        int32_t rs_len;
Packit d14fb6
Packit d14fb6
	static struct ipmi_rs rsp;	
Packit d14fb6
Packit d14fb6
        /* achu: FreeIPMI requests have the cmd as the first byte of
Packit d14fb6
         * the data.  Responses have cmd as the first byte and
Packit d14fb6
         * completion code as the second byte.  This differs from some
Packit d14fb6
         * other APIs, so it must be compensated for within the ipmitool
Packit d14fb6
         * interface.
Packit d14fb6
         */
Packit d14fb6
Packit d14fb6
	if (!intf || !req)
Packit d14fb6
		return NULL;
Packit d14fb6
Packit d14fb6
	if (!intf->opened && intf->open && intf->open(intf) < 0)
Packit d14fb6
		return NULL;
Packit d14fb6
Packit d14fb6
        if (req->msg.data_len > IPMI_BUF_SIZE)
Packit d14fb6
                return NULL;
Packit d14fb6
Packit d14fb6
        memset(rq_buf, '\0', IPMI_BUF_SIZE);
Packit d14fb6
        memset(rs_buf, '\0', IPMI_BUF_SIZE);
Packit d14fb6
        memcpy(rq_buf, &cmd, 1);
Packit d14fb6
Packit d14fb6
        if (req->msg.data)
Packit d14fb6
               memcpy(rq_buf + 1, req->msg.data, req->msg.data_len);
Packit d14fb6
Packit d14fb6
        if (intf->target_addr != 0
Packit d14fb6
            && intf->target_addr != IPMI_BMC_SLAVE_ADDR) {
Packit d14fb6
#if IPMI_INTF_FREE_BRIDGING
Packit d14fb6
                if ((rs_len = ipmi_cmd_raw_ipmb(dev,
Packit d14fb6
                                                intf->target_channel,
Packit d14fb6
                                                intf->target_addr,
Packit d14fb6
                                                lun, 
Packit d14fb6
                                                netfn,                    
Packit d14fb6
                                                rq_buf, 
Packit d14fb6
                                                req->msg.data_len + 1,
Packit d14fb6
                                                rs_buf, 
Packit d14fb6
                                                rs_buf_len)) < 0) {
Packit d14fb6
			if (verbose > 3)
Packit d14fb6
                      	        fprintf(stderr,
Packit d14fb6
                                	"ipmi_cmd_raw_ipmb: %s\n",
Packit d14fb6
                                	ipmi_ctx_strerror(ipmi_ctx_errnum(dev)));
Packit d14fb6
			/* Compared to FreeIPMI, user is expected to input
Packit d14fb6
			 * the target channel on the command line, it is not automatically
Packit d14fb6
			 * discovered.  So that is the likely cause of an error.
Packit d14fb6
			 *
Packit d14fb6
			 * Instead of returning an error, return a bad response so output
Packit d14fb6
			 * of ipmitool commands looks like other interfaces
Packit d14fb6
			 */
Packit d14fb6
			rs_len = 2;
Packit d14fb6
			rs_buf[0] = 0;
Packit d14fb6
			rs_buf[1] = 0xC1; /* invalid command */
Packit d14fb6
                }
Packit d14fb6
#else  /* !IPMI_INTF_FREE_BRIDGING */
Packit d14fb6
                if (verbose > 3)
Packit d14fb6
                        fprintf(stderr, "sensor bridging not supported in this driver version");
Packit d14fb6
		/* instead of returning an error, return a bad response so output
Packit d14fb6
	 	 * of ipmitool commands looks like other interfaces
Packit d14fb6
		 */
Packit d14fb6
		rs_len = 2;
Packit d14fb6
		rs_buf[0] = 0;
Packit d14fb6
		rs_buf[1] = 0xC1; /* invalid command */
Packit d14fb6
#endif  /* !IPMI_INTF_FREE_BRIDGING */
Packit d14fb6
        }
Packit d14fb6
        else {
Packit d14fb6
                if ((rs_len = ipmi_cmd_raw(dev,
Packit d14fb6
                                           lun, 
Packit d14fb6
                                           netfn,                    
Packit d14fb6
                                           rq_buf, 
Packit d14fb6
                                           req->msg.data_len + 1,
Packit d14fb6
                                           rs_buf, 
Packit d14fb6
                                           rs_buf_len)) < 0) {
Packit d14fb6
#if IPMI_INTF_FREE_0_3_0
Packit d14fb6
                        perror("ipmi_cmd_raw");
Packit d14fb6
#elif IPMI_INTF_FREE_0_4_0 || IPMI_INTF_FREE_0_5_0
Packit d14fb6
                        fprintf(stderr,
Packit d14fb6
                                "ipmi_cmd_raw: %s\n",
Packit d14fb6
                                ipmi_device_strerror(ipmi_device_errnum(dev)));
Packit d14fb6
#elif IPMI_INTF_FREE_0_6_0
Packit d14fb6
                        fprintf(stderr,
Packit d14fb6
                                "ipmi_cmd_raw: %s\n",
Packit d14fb6
                                ipmi_ctx_strerror(ipmi_ctx_errnum(dev)));
Packit d14fb6
#endif
Packit d14fb6
                        return NULL;
Packit d14fb6
                }
Packit d14fb6
        }
Packit d14fb6
Packit d14fb6
        memset(&rsp, 0, sizeof(struct ipmi_rs));
Packit d14fb6
	rsp.ccode = (unsigned char)rs_buf[1];
Packit d14fb6
	rsp.data_len = (int)rs_len - 2;
Packit d14fb6
Packit d14fb6
	if (!rsp.ccode && rsp.data_len)
Packit d14fb6
		memcpy(rsp.data, rs_buf + 2, rsp.data_len);
Packit d14fb6
Packit d14fb6
	return &rsp;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
struct ipmi_intf ipmi_free_intf = {
Packit d14fb6
	name:		"free",
Packit d14fb6
	desc:		"FreeIPMI IPMI Interface",
Packit d14fb6
	open:		ipmi_free_open,
Packit d14fb6
	close:		ipmi_free_close,
Packit d14fb6
	sendrecv:	ipmi_free_send_cmd,
Packit d14fb6
	target_addr:	IPMI_BMC_SLAVE_ADDR,
Packit d14fb6
};
Packit d14fb6