Blame src/plugins/free/free.c

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