⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipmilan_command.c

📁 在LINUX下实现HA的源代码
💻 C
字号:
/* $Id: ipmilan_command.c,v 1.1.2.5 2005/08/10 09:10:49 horms Exp $ *//* * This program is largely based on the ipmicmd.c program that's part of OpenIPMI package. *  * Copyright Intel Corp.  * Yixiong.Zou@intel.com */#include <stdio.h>#include <stdlib.h> // malloc()#include <unistd.h> // getopt()#include <string.h> // strerror()#include <netdb.h> // gethostbyname()#include <sys/types.h>#include <sys/socket.h>#include <syslog.h>#include <OpenIPMI/selector.h>#include <OpenIPMI/ipmi_conn.h>#include <OpenIPMI/ipmi_lan.h>#include <OpenIPMI/ipmi_smi.h>#include <OpenIPMI/ipmi_auth.h>#include <OpenIPMI/ipmi_msgbits.h>#include <OpenIPMI/ipmi_posix.h>#include "ipmilan.h"#include <stonith/stonith.h>#include <clplumbing/cl_log.h>// #define DUMP_MSG 0#define OPERATION_TIME_OUT 10os_handler_t *os_hnd;selector_t *os_sel;extern os_handler_t ipmi_os_cb_handlers;typedef enum ipmi_status {	/*	IPMI_CONNECTION_FAILURE,	IPMI_SEND_FAILURE,	IPMI_BAD_REQUEST,	IPMI_REQUEST_FAILED,	IPMI_TIME_OUT,	*/	IPMI_RUNNING = 99,} ipmi_status_t;static ipmi_status_t gstatus;typedef enum chassis_control_request {	POWER_DOWN = 0X00,	POWER_UP = 0X01,	POWER_CYCLE = 0X02,	HARD_RESET = 0X03,	PULSE_DIAGNOSTIC_INTERRUPT = 0X04,	SOFT_SHUTDOWN = 0X05} chassis_control_request_t;void dump_msg_data(ipmi_msg_t *msg, ipmi_addr_t *addr, char *type);void rsp_handler(ipmi_con_t *ipmi, ipmi_msg_t *rsp);void send_ipmi_cmd(ipmi_con_t *con, int request);void timed_out(selector_t *sel, sel_timer_t *timer, void *data);void timed_out(selector_t  *sel, sel_timer_t *timer, void *data){	syslog(LOG_ERR, "IPMI operation timed out... :(\n");	gstatus = S_TIMEOUT;}voiddump_msg_data(ipmi_msg_t *msg, ipmi_addr_t *addr, char *type){	ipmi_system_interface_addr_t *smi_addr = NULL;	int i;	ipmi_ipmb_addr_t *ipmb_addr = NULL;	if (addr->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {		smi_addr = (struct ipmi_system_interface_addr *) addr;	} else if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE) 			|| (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) {		ipmb_addr = (struct ipmi_ipmb_addr *) addr;	}	if (smi_addr) {		fprintf(stderr, "%2.2x %2.2x %2.2x %2.2x ", 			addr->channel,			msg->netfn,			smi_addr->lun,			msg->cmd);	} else {		fprintf(stderr, "%2.2x %2.2x %2.2x %2.2x ", 			addr->channel,			msg->netfn,			ipmb_addr->lun,			msg->cmd);	}	for (i = 0; i < msg->data_len; i++) {		if (((i%16) == 0) && (i != 0)) {			printf("\n            ");		}		fprintf(stderr, "%2.2x ", msg->data[i]);	}	fprintf(stderr, "\n");}/* * This function gets called after the response comes back * from the IPMI device.  *  * Some IPMI device does not return success, 0x00, to the  * remote node when the power-reset was issued. *  * The host who sent the ipmi cmd might get a 0xc3, * a timeout instead.  This creates problems for  * STONITH operation, where status is critical. :(  *  * Right now I am only checking 0xc3 as the return. * If your IPMI device returns some wired code after  * reset, you might want to add it in this code block. * */voidrsp_handler(ipmi_con_t *ipmi, ipmi_msg_t *rsp){	int rv;	int * request;	request = (void *) rsp->data;#if 0	dump_msg_data(rsp, addr, NULL);#endif	rv = rsp->data[0];  	/* some IPMI device might not issue 0x00, success, for reset command.	   instead, a 0xc3, timeout, is returned. */	if (rv == 0x00 || 		(rv == 0xc3 && *request <= ST_POWEROFF && *request >= ST_GENERIC_RESET ) ) {		gstatus = S_OK;	} else {		gstatus = S_RESETFAIL;	}	free(request);	return;}voidsend_ipmi_cmd(ipmi_con_t *con, int request){	ipmi_addr_t addr;	unsigned int addr_len;	ipmi_msg_t msg;	struct ipmi_system_interface_addr *si;	int rv;	ipmi_msg_t msgi;	// chassis control command request is only 1 byte long	unsigned char cc_data = POWER_CYCLE; 	si = (void *) &addr;	si->lun = 0x00;	si->channel = IPMI_BMC_CHANNEL;	si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;	addr_len = sizeof(*si);	msg.netfn = IPMI_CHASSIS_NETFN;	msg.cmd = IPMI_CHASSIS_CONTROL_CMD;	msg.data = &cc_data;	msg.data_len = 1;	switch (request) {		case ST_POWERON:			cc_data = POWER_DOWN;			break;		case ST_POWEROFF:			cc_data = POWER_UP;			break;		case ST_GENERIC_RESET:			cc_data = POWER_CYCLE;			break;		case ST_IPMI_STATUS:			msg.netfn = IPMI_APP_NETFN;			msg.cmd = IPMI_GET_DEVICE_ID_CMD;			msg.data = NULL;			msg.data_len = 0;			break;		default:			gstatus = S_INVAL;			return;	}	msgi.data = (void *) malloc(sizeof(int));	*((unsigned char *)msgi.data) = request;	rv = con->send_command(con, &addr, addr_len, &msg, (ipmi_ll_rsp_handler_t) rsp_handler, (void *) &msgi);	if (rv == -1) {		syslog(LOG_ERR, "Error sending IPMI command: %x\n", rv);		gstatus = S_ACCESS;	}	return;}static voidcon_changed_handler(ipmi_con_t *ipmi,			int err,			unsigned int port_num,			int still_connected,			void *cb_data){	int * request;	if (err) {		syslog(LOG_ERR, "Unable to setup connection: %x\n", err);		return;	}	request = (int *) cb_data;	send_ipmi_cmd(ipmi, *request);}static intsetup_ipmi_conn(struct ipmilanHostInfo * host, int request){	int rv;	struct hostent *ent;	struct in_addr lan_addr[2];	int lan_port[2];	int num_addr = 1;	int authtype = 0;	int privilege = 0;	char username[17];	char password[17];	static ipmi_con_t *con;	sel_timer_t * timer;	struct timeval timeout;	os_hnd = ipmi_posix_get_os_handler();	if (!os_hnd) {	    	syslog(LOG_ERR, "ipmi_smi_setup_con: Unable to allocate os handler");		return 1;	}	rv = sel_alloc_selector(os_hnd, &os_sel);	if (rv) {		syslog(LOG_ERR, "Could not alloctate selector\n");		return rv;	}    	ipmi_posix_os_handler_set_sel(os_hnd, os_sel);	rv = ipmi_init(os_hnd);	if (rv) {		syslog(LOG_ERR, "ipmi_init erro: %d ", rv);		return rv;	}	ent = gethostbyname(host->ipaddr);	if (!ent) {		syslog(LOG_ERR, "gethostbyname failed: %s\n", strerror(h_errno));		return 1;	}	memcpy(&lan_addr[0], ent->h_addr_list[0], ent->h_length);	lan_port[0] = host->portnumber;	lan_port[1] = 0;	authtype = host->authtype;	privilege = host->privilege;	memcpy(username, host->username, sizeof(username));	memcpy(password, host->password, sizeof(password));	rv = ipmi_lan_setup_con(lan_addr, lan_port, num_addr, 				authtype, privilege,				username, strlen(username),				password, strlen(password),				os_hnd, os_sel,				&con);	if (rv) {		syslog(LOG_ERR, "ipmi_lan_setup_con: %s\n", strerror(rv));		return S_ACCESS;	}	/* in the OpenIPMI 1.3.x implementation the callback function was	 * called set_con_change_handler(), now with the OpenIPMI 2.0.x	 * implementation it has changed to add_con_change_handler(). Check out:	 *	 * http://cvs.sourceforge.net/viewcvs.py/openipmi/OpenIPMI/include/OpenIPMI/ipmi_conn.h?r1=1.27&r2=1.28	 */	con->add_con_change_handler(con, con_changed_handler, &request);	gstatus = IPMI_RUNNING;	rv = con->start_con(con);	if (rv) {		syslog(LOG_ERR, "Could not start IPMI connection: %x\n", rv);		gstatus = S_BADCONFIG;		return rv;	}	gettimeofday(&timeout, NULL);	timeout.tv_sec += OPERATION_TIME_OUT;	timeout.tv_usec += 0;	sel_alloc_timer(os_sel, timed_out, NULL, &timer);	sel_start_timer(timer, &timeout);        while (1) {                rv = sel_select(os_sel, NULL, 0, NULL, NULL);		if (gstatus != IPMI_RUNNING) {			break;		}        }	sel_free_timer(timer);	con->close_connection(con);	ipmi_shutdown();	return gstatus;}intdo_ipmi_cmd(struct ipmilanHostInfo * host, int request){	return setup_ipmi_conn(host, request);}voidposix_vlog(char *format, enum ipmi_log_type_e log_type, va_list ap){    int do_nl = 1;     switch(log_type)    {        case IPMI_LOG_INFO:            syslog(LOG_INFO, "INFO: ");            break;                                                                                                                                                                     case IPMI_LOG_WARNING:            syslog(LOG_INFO, "WARN: ");            break;                                                                                                                                                                     case IPMI_LOG_SEVERE:            syslog(LOG_INFO, "SEVR: ");            break;                                                                                                                                                                     case IPMI_LOG_FATAL:            syslog(LOG_INFO, "FATL: ");            break;                                                                                                                                                                     case IPMI_LOG_ERR_INFO:            syslog(LOG_INFO, "EINF: ");            break;                                                                                                                                                                     case IPMI_LOG_DEBUG_START:            do_nl = 0;            /* FALLTHROUGH */        case IPMI_LOG_DEBUG:            syslog(LOG_INFO, "DEBG: ");            break;                                                                                                                                                                     case IPMI_LOG_DEBUG_CONT:            do_nl = 0;            /* FALLTHROUGH */        case IPMI_LOG_DEBUG_END:            break;    }                                                                                                                                                             }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -