Hi,

On Thu, Jan 17, 2008 at 05:23:15PM -0600, Corey Minyard wrote:
> I know why you are getting the segfault, which I will fix, but I do not 
> know why the initialization is failing and causing this.
>
> Can you step through ipmi_init() with the debugger and see which exact 
> function is failing to initialize?

Sorry for the delay. Did some changes in the meantime and now I
can't reproduce the coredumps anymore. I think that they were
caused by calling ipmi_init twice. If you want to pursue that
issue, I can retrieve an old version and try to reproduce the
segfault.

But I still can't make the thing work. This is the output from
ipmilan:

INFO: ipmi_lan.c(connection_up): Connection 0 to the BMC is up
INFO: ipmi_lan.c(connection_up): Connection to the BMC restored
0f 07 00 01 ff 
** INFO: IPMI request 4 failed: ff

The openipmicmd with same parameters returns good status. What's
funny is that the stuff on the wire seems to be very similar in
both cases---I can see the very same response as with ipmicmd
when running ipmilan.

Looked for a long time at the source of ipmicmd and ipmilan, but
can't find any problems. Walked through both with gdb, still
didn't get any wiser. If you could take a look at the code and
tell me what's wrong with it, I'd appreciate very much. It has
been done around openipmi release 1.0 by a guy from Intel, but
he's not maintaining it any more.

Cheers,

Dejan


> -corey
>
> Dejan Muhamedagic wrote:
>> Hi,
>>
>> On Thu, Jan 17, 2008 at 09:58:42AM -0600, Corey Minyard wrote:
>>   
>>> Bugs have been fixed in this code that might solve the problem.  Is there 
>>> any way you can try a newer version of the library?
>>>     
>>
>> Tried with the latest (2.0.13) from sourceforge. The same thing:
>>
>> Thread 1 (process 12048):
>> #0  0x00000000 in ?? ()
>> No symbol table info available.
>> #1  0xb7f5c786 in locked_list_remove (ll=0x8056620, item1=0xb7b44700,     
>> item2=0x0) at locked_list.c:296
>>      rv = <value optimized out>
>> #2  0xb7aee30f in _ipmi_fru_deregister_decoder (
>>     op=0xb7b44700 <process_fru_spd_info>) at fru.c:270
>> No locals.
>> #3  0xb7b446f0 in _ipmi_fru_spd_decoder_shutdown () at 
>> fru_spd_decode.c:327
>> No locals.
>> #4  0xb7ad56ea in ipmi_init (handler=0x8056600) at ipmi.c:1029
>>      rv = 11
>> #5  0xb7f680ea in setup_ipmi_conn (host=0x8051128, request=4)
>>     at ipmilan_command.c:293
>>      rv = 0
>>      ent = (struct hostent *) 0xb7f4c455
>>      lan_addr = {{s_addr = 3086282740}, {s_addr = 3086527648}}
>>      lan_port = {134549680, -1079889992}
>>      num_addr = 1
>>      authtype = 0
>>      privilege = 0
>>      username = "..."
>>      password = "..."
>>      timer = (sel_timer_t *) 0xb7c2a179
>>      timeout = {tv_sec = 134590944, tv_usec = -1079890040}
>>      con = (ipmi_con_t *) 0x80575c0
>> #6  0xb7f68457 in do_ipmi_cmd (host=0x8051128, request=4)
>>     at ipmilan_command.c:372
>>
>> Cheers,
>>
>> Dejan
>>
>>   
>>> -corey
>>>
>>> Dejan Muhamedagic wrote:
>>>     
>>>> Hi,
>>>>
>>>> This is on a openSUSE 10.3 and ipmi is:
>>>>
>>>> OpenIPMI-devel-2.0.7-102
>>>>
>>>> The backtrace:
>>>>
>>>> Thread 1 (process 8787):
>>>> #0  0x00000000 in ?? ()
>>>> No symbol table info available.
>>>> #1  0xb7f8a8b6 in locked_list_remove () from 
>>>> /usr/lib/libOpenIPMIutils.so.0
>>>> No symbol table info available.
>>>> #2  0xb7b1b19f in _ipmi_fru_deregister_decoder ()
>>>>    from /usr/lib/libOpenIPMI.so.0
>>>> No symbol table info available.
>>>> #3  0xb7b730f0 in _ipmi_fru_spd_decoder_shutdown ()
>>>>    from /usr/lib/libOpenIPMI.so.0
>>>> No symbol table info available.
>>>> #4  0xb7b0254a in ipmi_init () from /usr/lib/libOpenIPMI.so.0
>>>> No symbol table info available.
>>>> #5  0xb7f95b1a in do_ipmi_cmd (host=0x8051028, request=4)
>>>>     at ipmilan_command.c:293
>>>> No locals.
>>>> #6  0xb7f955f7 in ipmilan_status (s=0x8050f80) at ipmilan.c:231
>>>>    rv = <value optimized out>
>>>>    node = (struct ipmilanHostInfo *) 0x8051028
>>>>    ret = 0
>>>>    __FUNCTION__ = "ipmilan_status"
>>>>
>>>> The code is a bit old (from the openipmi 1.x times) and I'm
>>>> trying to revive it, so far unsuccessfully. I looked at it for a
>>>> while, but can't figure out what's wrong. ipmi_init obviously
>>>> fails and segfaults when trying to cleanup. The same device talks
>>>> without problems to the ipmitool.
>>>>
>>>> The code is below, with error checking removed for clarity.
>>>>
>>>> Cheers,
>>>> str2a:     .asciz "T2a\n"
>>>>
>>>> Dejan
>>>>
>>>>    os_hnd = ipmi_posix_get_os_handler();
>>>>    rv = sel_alloc_selector(os_hnd, &os_sel);
>>>>     ipmi_posix_os_handler_set_sel(os_hnd, os_sel);
>>>>    rv = ipmi_init(os_hnd);
>>>>    ent = gethostbyname(host->ipaddr);
>>>>    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 OPENIPMI_VERSION_MAJOR < 2
>>>>    con->set_con_change_handler(con, con_changed_handler, &request);
>>>> #else
>>>>    con->add_con_change_handler(con, con_changed_handler, &request);
>>>> #endif
>>>>    rv = con->start_con(con);
>>>>
>>>>    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();
>>>>
>>>>
>>>> -------------------------------------------------------------------------
>>>> This SF.net email is sponsored by: Microsoft
>>>> Defy all challenges. Microsoft(R) Visual Studio 2008.
>>>> http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
>>>> _______________________________________________
>>>> Openipmi-developer mailing list
>>>> [email protected]
>>>> https://lists.sourceforge.net/lists/listinfo/openipmi-developer
>>>>         
>>
>> -------------------------------------------------------------------------
>> This SF.net email is sponsored by: Microsoft
>> Defy all challenges. Microsoft(R) Visual Studio 2008.
>> http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
>> _______________________________________________
>> Openipmi-developer mailing list
>> [email protected]
>> https://lists.sourceforge.net/lists/listinfo/openipmi-developer
>>   
>
/*
 * This program is largely based on the ipmicmd.c program that's part of OpenIPMI package.
 * 
 * Copyright Intel Corp. 
 * [EMAIL PROTECTED]
 *
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#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 <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>

#include <pils/plugin.h>
extern const PILPluginImports*  PluginImports;

/* #define DUMP_MSG 0 */
#define OPERATION_TIME_OUT 10

os_handler_t *os_hnd=NULL;
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, const char *type);
int rsp_handler(ipmi_con_t *ipmi, ipmi_msgi_t *rspi);

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)
{
	PILCallLog(PluginImports->log,PIL_CRIT, "IPMI operation timed out... :(\n");
	gstatus = S_TIMEOUT;
}

void
dump_msg_data(ipmi_msg_t *msg, ipmi_addr_t *addr, const 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;

		fprintf(stderr, "%2.2x %2.2x %2.2x %2.2x ", 
			addr->channel,
			msg->netfn,
			smi_addr->lun,
			msg->cmd);
	} else if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE) 
			|| (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) {
		ipmb_addr = (struct ipmi_ipmb_addr *) addr;
		
		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.
 *
 */

int
rsp_handler(ipmi_con_t *ipmi, ipmi_msgi_t *rspi)
{
	int rv;
	long request;

	dump_msg_data(&rspi->msg, &rspi->addr, "response");
	request = (long) rspi->data1;

	if( !rspi || !(rspi->msg.data) ) {
		PILCallLog(PluginImports->log,PIL_CRIT, "No data received\n");
		gstatus = S_RESETFAIL;
		return IPMI_MSG_ITEM_NOT_USED;
	}
	rv = rspi->msg.data[0];
	/* some IPMI device might not issue 0x00, success, for reset command.
	   instead, a 0xc3, timeout, is returned. */
	if (rv == 0x00 || 
		((rv == 0xc3 || rv == 0xff) && request == ST_GENERIC_RESET) ) {
		gstatus = S_OK;
	} else {
		PILCallLog(PluginImports->log,PIL_INFO
		, "IPMI request %ld failed: %x\n", request, rv);
		gstatus = S_RESETFAIL;
	}
	return IPMI_MSG_ITEM_NOT_USED;
}

void
send_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_msgi_t *rspi;
	/* 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_UP;
			break;

		case ST_POWEROFF:
			cc_data = POWER_DOWN;
			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_len = 0;
			break;

		default:
			gstatus = S_INVAL;
			return;
	}

 	gstatus = S_ACCESS;
	rspi = calloc(1, sizeof(ipmi_msgi_t));
	if (NULL == rspi) {
		PILCallLog(PluginImports->log,PIL_CRIT, "Error sending IPMI command: Out of memory\n");
	} else {
		rspi->data1 = (void *) (long) request;
		rv = con->send_command(con, &addr, addr_len, &msg, rsp_handler, rspi);
		if (rv == -1) {
			PILCallLog(PluginImports->log,PIL_CRIT, "Error sending IPMI command: %x\n", rv);
		}
	}

	return;
}

static int request_done = 0;

static void
con_changed_handler(ipmi_con_t *ipmi, int err, unsigned int port_num,
			int still_connected, void *cb_data)
{
	int * request;

	if (err) {
		PILCallLog(PluginImports->log,PIL_CRIT, "Unable to setup connection: %x\n", err);
		return;
	}

	if( !request_done ) {
		request = (int *) cb_data;
		send_ipmi_cmd(ipmi, *request);
		request_done = 1;
	}
}

static int
setup_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;

	request_done = 0;
	if( !os_hnd ) { /* 	already initialized? */
		os_hnd = ipmi_posix_get_os_handler();
		if (!os_hnd) {
				PILCallLog(PluginImports->log,PIL_CRIT, "ipmi_smi_setup_con: Unable to allocate os handler");
			return 1;
		}

		rv = sel_alloc_selector(os_hnd, &os_sel);
		if (rv) {
			PILCallLog(PluginImports->log,PIL_CRIT, "Could not allocate selector\n");
			return rv;
		}

		ipmi_posix_os_handler_set_sel(os_hnd, os_sel);

		rv = ipmi_init(os_hnd);
		if (rv) {
			PILCallLog(PluginImports->log,PIL_CRIT, "ipmi_init erro: %d ", rv);
			return rv;
		}
	}

	ent = gethostbyname(host->ipaddr);
	if (!ent) {
		PILCallLog(PluginImports->log,PIL_CRIT, "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) {
		PILCallLog(PluginImports->log,PIL_CRIT, "ipmi_lan_setup_con: %s\n", strerror(rv));
		return S_ACCESS;
	}

#if OPENIPMI_VERSION_MAJOR < 2
	con->set_con_change_handler(con, con_changed_handler, &request);
#else
	con->add_con_change_handler(con, con_changed_handler, &request);
#endif

	gstatus = IPMI_RUNNING;

	rv = con->start_con(con);
	if (rv) {
		PILCallLog(PluginImports->log,PIL_CRIT, "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;
}

int
do_ipmi_cmd(struct ipmilanHostInfo * host, int request)
{
	return setup_ipmi_conn(host, request);
}

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Openipmi-developer mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openipmi-developer

Reply via email to