Exemplo n.º 1
0
static void
sol_update_bitrate(lmc_data_t *mc)
{
    ipmi_sol_t *sol = ipmi_mc_get_sol(mc);
    soldata_t *sd = sol->soldata;

    sd->update_bitrate(ipmi_mc_get_sol(mc));
}
Exemplo n.º 2
0
static void sol_set_history_return_size(lmc_data_t    *mc,
					msg_t         *msg,
					unsigned char *rdata,
					unsigned int  *rdata_len,
					void          *cb_data)
{
    ipmi_sol_t *sol = ipmi_mc_get_sol(mc);
    soldata_t *sd = sol->soldata;
    unsigned int size;

    if (msg->len < 1) {
	rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC;
	*rdata_len = 1;
	return;
    }

    if (!sd) {
	rdata[0] = IPMI_NOT_PRESENT_CC;
	*rdata_len = 1;
	return;
    }

    size = msg->data[0] * 1024;
    if (size >= sol->history_size || size == 0)
	sd->history_return_size = 0;
    else
	sd->history_return_size = size;

    rdata[0] = 0;
    *rdata_len = 1;
}
Exemplo n.º 3
0
unsigned char *
sol_set_frudata(lmc_data_t *mc, unsigned int *size)
{
    ipmi_sol_t *sol = ipmi_mc_get_sol(mc);

    return copy_history_buffer(sol, size);
}
Exemplo n.º 4
0
void sol_free_frudata(lmc_data_t *mc, unsigned char *data)
{
    ipmi_sol_t *sol = ipmi_mc_get_sol(mc);
    soldata_t *sd = sol->soldata;

    if (data)
	sd->sys->free(sd->sys, data);
}
Exemplo n.º 5
0
int
write_sol_config(lmc_data_t *mc)
{
    ipmi_sol_t *sol;
    persist_t *p;

    sol = ipmi_mc_get_sol(mc);

    p = alloc_persist("sol.mc%2.2x", ipmi_mc_get_ipmb(mc));
    if (!p)
	return ENOMEM;

    sol = ipmi_mc_get_sol(mc);

    add_persist_int(p, sol->solparm.enabled, "enabled");
    add_persist_int(p, sol->solparm.bitrate_nonv, "bitrate");

    write_persist(p);
    free_persist(p);
    return 0;
}
Exemplo n.º 6
0
static void
handle_sol_payload(lanserv_data_t *lan, msg_t *msg)
{
    ipmi_sol_t *sol;
    channel_t *channel = &lan->channel;
    lmc_data_t *mc;

    mc = channel->get_associated_mc(channel, msg->sid,
				    IPMI_RMCPP_PAYLOAD_TYPE_SOL);
    if (!mc)
	return;

    sol = ipmi_mc_get_sol(mc);
    if (msg->sid == sol->session_id)
	handle_sol_port_payload(lan, sol, msg);
    else if (msg->sid == sol->history_session_id)
	handle_sol_history_payload(lan, sol, msg);
}
Exemplo n.º 7
0
static void sol_get_history_return_size(lmc_data_t    *mc,
					msg_t         *msg,
					unsigned char *rdata,
					unsigned int  *rdata_len,
					void          *cb_data)
{
    ipmi_sol_t *sol = ipmi_mc_get_sol(mc);
    soldata_t *sd = sol->soldata;

    if (!sd) {
	rdata[0] = IPMI_NOT_PRESENT_CC;
	*rdata_len = 1;
	return;
    }

    rdata[0] = 0;
    rdata[1] = sd->history_return_size / 1024;
    *rdata_len = 2;
}
Exemplo n.º 8
0
int
read_sol_config(sys_data_t *sys)
{
    unsigned int i;
    int rv;

    for (i = 0; i < IPMI_MAX_MCS; i++) {
	lmc_data_t *mc = sys->ipmb_addrs[i];
	ipmi_sol_t *sol;
	persist_t *p;
	long iv;

	if (!mc)
	    continue;
	sol = ipmi_mc_get_sol(mc);
	if (!sol->configured)
	    continue;

	sys->sol_present = 1;

	sol->solparm.enabled = 1;
	sol->solparm.bitrate_nonv = 0;

	p = read_persist("sol.mc%2.2x", ipmi_mc_get_ipmb(mc));
	if (p) {
	    if (!read_persist_int(p, &iv, "enabled"))
		sol->solparm.enabled = iv;

	    if (!read_persist_int(p, &iv, "bitrate"))
		sol->solparm.bitrate_nonv = iv;

	    sol->solparm.bitrate = sol->solparm.bitrate_nonv;

	    free_persist(p);
	}
	rv = sol_init_mc(sys, mc);
	if (rv)
	    return rv;
    }

    return 0;
}
Exemplo n.º 9
0
void
ipmi_sol_deactivate(lmc_data_t    *mc,
		    channel_t     *channel,
		    msg_t         *msg,
		    unsigned char *rdata,
		    unsigned int  *rdata_len)
{
    ipmi_sol_t *sol = ipmi_mc_get_sol(mc);
    unsigned int instance;
    uint32_t session_id;

    instance = msg->data[1] & 0xf;
    if (instance == 1) {
	if (!sol->active) {
	    *rdata = 0x80; /* Payload already deactivated */
	    *rdata_len = 1;
	    return;
	}
	session_id = sol->session_id;
    } else if (instance == 2) {
	if (!sol->history_active) {
	    *rdata = 0x80; /* Payload already deactivated */
	    *rdata_len = 1;
	    return;
	}
	session_id = sol->history_session_id;
    } else {
	rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
	*rdata_len = 1;
	return;
    }

    sol_session_closed(mc, session_id, sol);
    channel->set_associated_mc(channel, session_id, msg->data[0] & 0xf, NULL,
			       NULL, NULL, NULL);

    rdata[0] = 0;
    *rdata_len = 1;
}
Exemplo n.º 10
0
void
ipmi_sol_activate(lmc_data_t    *mc,
		  channel_t     *channel,
		  msg_t         *msg,
		  unsigned char *rdata,
		  unsigned int  *rdata_len)
{
    ipmi_sol_t *sol = ipmi_mc_get_sol(mc);
    soldata_t *sd = sol->soldata;
    uint16_t port;
    int rv;
    msg_t *dmsg;
    unsigned int instance;

    if (!sol->solparm.enabled) {
	rdata[0] = 0x81; /* Payload is disabled. */
	*rdata_len = 1;
	return;
    }

    /*
     * FIXME - we are currently ignoring all the payload encryption and
     * authentication bits in the message.
     */

    instance = msg->data[1] & 0xf;
    if (instance == 1) {
	if (sol->active) {
	    *rdata = 0x80; /* Payload already active */
	    *rdata_len = 1;
	    return;
	}
	dmsg = &sd->dummy_send_msg;
    } else if (instance == 2 && sol->history_size) {
	if (sol->history_active) {
	    *rdata = 0x80; /* Payload already active */
	    *rdata_len = 1;
	    return;
	}
	dmsg = &sd->history_dummy_send_msg;
    } else {
	rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
	*rdata_len = 1;
	return;
    }

    dmsg->src_addr = sd->sys->alloc(sd->sys, msg->src_len);
    if (!dmsg->src_addr) {
	rdata[0] = IPMI_OUT_OF_SPACE_CC;
	*rdata_len = 1;
	return;
    }
    memcpy(dmsg->src_addr, msg->src_addr, msg->src_len);
    dmsg->src_len = msg->src_len;
    dmsg->rmcpp.payload = IPMI_RMCPP_PAYLOAD_TYPE_SOL;

    rv = channel->set_associated_mc(channel, msg->sid, msg->data[0] & 0xf, mc,
				    &port, sol_session_closed, sol);
    if (rv == EBUSY) {
	sd->sys->free(sd->sys, dmsg->src_addr);
	dmsg->src_addr = NULL;
	rdata[0] = IPMI_NODE_BUSY_CC;
	*rdata_len = 1;
	return;
    } else if (rv) {
	sd->sys->free(sd->sys, dmsg->src_addr);
	dmsg->src_addr = NULL;
	rdata[0] = IPMI_UNKNOWN_ERR_CC;
	*rdata_len = 1;
	return;
    }

    dmsg->sid = msg->sid;

    if (instance == 1) {
	rv = sd->activate(sol, msg);
	if (rv) {
	    sd->sys->free(sd->sys, dmsg->src_addr);
	    dmsg->src_addr = NULL;
	    rdata[0] = IPMI_UNKNOWN_ERR_CC;
	    *rdata_len = 1;
	    return;
	}

	sol->active = 1;
	sol->session_id = msg->sid;
	sd->channel = channel;
	sd->outlen = 0;
	ipmi_set_uint16(rdata + 5, sizeof(sd->inbuf));
	ipmi_set_uint16(rdata + 7, sizeof(sd->outbuf));
    } else if (instance == 2 && sol->history_size) {
	struct timeval tv;

	sd->history_copy = copy_history_buffer(sol, &sd->history_copy_size);
	if (!sd->history_copy) {
	    rdata[0] = IPMI_OUT_OF_SPACE_CC;
	    *rdata_len = 1;
	    return;
	}
	sd->history_pos = 0;
	sol->history_active = 1;
	sol->history_session_id = msg->sid;
	sd->history_channel = channel;
	ipmi_set_uint16(rdata + 5, MAX_HISTORY_SEND);
	ipmi_set_uint16(rdata + 7, MAX_HISTORY_SEND);
	tv.tv_sec = 0;
	tv.tv_usec = 0; /* Send immediately */
	sd->history_num_sends = 0;
	sd->sys->start_timer(sd->history_timer, &tv);
    }

    rdata[0] = 0;
    ipmi_set_uint32(rdata + 1, 0);
    ipmi_set_uint16(rdata + 9, port);
    ipmi_set_uint16(rdata + 11, 0xffff);
    *rdata_len = 13;
}
Exemplo n.º 11
0
int
sol_init_mc(sys_data_t *sys, lmc_data_t *mc)
{
    ipmi_sol_t *sol = ipmi_mc_get_sol(mc);
    soldata_t *sd;

    sd = sys->alloc(sys, sizeof(*sd));
    if (!sd)
	return ENOMEM;
    memset(sd, 0, sizeof(*sd));
    sd->sys = sys;
    sol->soldata = sd;

    if (sol->tcpdest)
	sol_tcp_setup(sol);
    else
	sol_serial_setup(sol);
    
    if (sys->alloc_timer(sys, sol_timeout, sol, &sd->timer)) {
	sys->free(sys, sd);
	return ENOMEM;
    }

    if (sol->history_size) {
	if (sys->alloc_timer(sys, sol_history_timeout, sol,
			     &sd->history_timer)) {
	    sys->free_timer(sd->timer);
	    sys->free(sys, sd);
	    return ENOMEM;
	}

	sd->history = sys->alloc(sys, sol->history_size);
	if (!sd->history) {
	    sys->free_timer(sd->history_timer);
	    sys->free_timer(sd->timer);
	    sys->free(sys, sd);
	    return ENOMEM;
	}

	if (sol->backupfile) {
	    FILE *f = fopen(sol->backupfile, "r");
	    if (f) {
		/* Ignore errors, it doesn't really matter. */
		fseek(f, -sol->history_size, SEEK_END);
		sd->history_end = fread(sd->history, 1, sol->history_size, f);
		sd->history_end--; /* end point to last, not one after. */
		fclose(f);
	    }
	}
    }

    sd->backupfilehandler.handler = handle_sol_shutdown;
    sd->backupfilehandler.info = sol;
    ipmi_register_shutdown_handler(&sd->backupfilehandler);

    sd->fd = -1;
    sd->curr_packet_seq = 1;
    sd->history_curr_packet_seq = 1;
    sd->logchan = ipmi_mc_get_channelset(mc)[0];

    if (sol_port_init(sol)) {
	/* Retry in 10 seconds. */
	struct timeval tv;

	tv.tv_sec = 10;
	tv.tv_usec = 0;
	sd->sys->start_timer(sd->timer, &tv);
    }

    return 0;
}
Exemplo n.º 12
0
/* Need to make this a function main called from a GO main wrapper */
int
ipmi_sim_main(int argc, const char *argv[])
{
    sys_data_t  sysinfo;
    misc_data_t data;
    int err, rv = 1;
    int i;
    poptContext poptCtx;
    struct timeval tv;
    console_info_t stdio_console;
    struct sigaction act;
    os_hnd_fd_id_t *conid;
    lmc_data_t *mc;
    int print_version = 0;

    poptCtx = poptGetContext(argv[0], argc, argv, poptOpts, 0);
    while ((i = poptGetNextOpt(poptCtx)) >= 0) {
	switch (i) {
	    case 'd':
		debug++;
		break;
	    case 'n':
		nostdio = 1;
		break;
	    case 'v':
		print_version = 1;
		break;
	}
    }
    poptFreeContext(poptCtx);

    printf("IPMI Simulator version %s\n", PVERSION);

    data.os_hnd = ipmi_posix_setup_os_handler();
    if (!data.os_hnd) {
	fprintf(stderr, "Unable to allocate OS handler\n");
	exit(1);
    }

    err = os_handler_alloc_waiter_factory(data.os_hnd, 0, 0,
					  &data.waiter_factory);
    if (err) {
	fprintf(stderr, "Unable to allocate waiter factory: 0x%x\n", err);
	exit(1);
    }

    err = data.os_hnd->alloc_timer(data.os_hnd, &data.timer);
    if (err) {
	fprintf(stderr, "Unable to allocate timer: 0x%x\n", err);
	exit(1);
    }

    sysinfo_init(&sysinfo);
    sysinfo.info = &data;
    sysinfo.alloc = balloc;
    sysinfo.free = bfree;
    sysinfo.get_monotonic_time = ipmi_get_monotonic_time;
    sysinfo.get_real_time = ipmi_get_real_time;
    sysinfo.alloc_timer = ipmi_alloc_timer;
    sysinfo.start_timer = ipmi_start_timer;
    sysinfo.stop_timer = ipmi_stop_timer;
    sysinfo.free_timer = ipmi_free_timer;
    sysinfo.add_io_hnd = ipmi_add_io_hnd;
    sysinfo.io_set_hnds = ipmi_io_set_hnds;
    sysinfo.io_set_enables = ipmi_io_set_enables;
    sysinfo.remove_io_hnd = ipmi_remove_io_hnd;
    sysinfo.gen_rand = sys_gen_rand;
    sysinfo.debug = debug;
    sysinfo.log = sim_log;
    sysinfo.csmi_send = smi_send;
    sysinfo.clog = sim_chan_log;
    sysinfo.calloc = ialloc;
    sysinfo.cfree = ifree;
    sysinfo.lan_channel_init = lan_channel_init;
    sysinfo.ser_channel_init = ser_channel_init;
    data.sys = &sysinfo;

    err = pipe(sigpipeh);
    if (err) {
	perror("Creating signal handling pipe");
	exit(1);
    }

    act.sa_handler = handle_sigchld;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    
    err = sigaction(SIGCHLD, &act, NULL);
    if (err) {
	perror("setting up sigchld sigaction");
	exit(1);
    }

    err = data.os_hnd->add_fd_to_wait_for(data.os_hnd, sigpipeh[0],
					  sigchld_ready, &data,
					  NULL, &conid);
    if (err) {
	fprintf(stderr, "Unable to sigchld pipe wait: 0x%x\n", err);
	exit(1);
    }

    data.emu = ipmi_emu_alloc(&data, sleeper, &sysinfo);

    /* Set this up for console I/O, even if we don't use it. */
    stdio_console.data = &data;
    stdio_console.outfd = 1;
    stdio_console.pos = 0;
    stdio_console.echo = 1;
    stdio_console.shutdown_on_close = 1;
    stdio_console.telnet = 0;
    stdio_console.tn_pos = 0;
    if (nostdio) {
	stdio_console.out.printf = dummy_printf;
	stdio_console.out.data = &stdio_console;
    } else {
	stdio_console.out.printf = emu_printf;
	stdio_console.out.data = &stdio_console;
    }
    stdio_console.next = NULL;
    stdio_console.prev = NULL;
    data.consoles = &stdio_console;

    err = ipmi_mc_alloc_unconfigured(&sysinfo, 0x20, &mc);
    if (err) {
	if (err == ENOMEM)
	    fprintf(stderr, "Out of memory allocation BMC MC\n");
	exit(1);
    }
    sysinfo.mc = mc;
    sysinfo.chan_set = ipmi_mc_get_channelset(mc);
    sysinfo.startcmd = ipmi_mc_get_startcmdinfo(mc);
    sysinfo.cpef = ipmi_mc_get_pef(mc);
    sysinfo.cusers = ipmi_mc_get_users(mc);
    sysinfo.sol = ipmi_mc_get_sol(mc);

    if (read_config(&sysinfo, config_file, print_version))
	exit(1);

    if (print_version)
	exit(0);

    if (!sysinfo.name) {
	fprintf(stderr, "name not set in config file\n");
	exit(1);
    }

    err = persist_init("ipmi_sim", sysinfo.name, statedir);
    if (err) {
	fprintf(stderr, "Unable to initialize persistence: %s\n",
		strerror(err));
	exit(1);
    }

    read_persist_users(&sysinfo);

    err = sol_init(&sysinfo);
    if (err) {
	fprintf(stderr, "Unable to initialize SOL: %s\n",
		strerror(err));
	goto out;
    }

    err = read_sol_config(&sysinfo);
    if (err) {
	fprintf(stderr, "Unable to read SOL configs: %s\n",
		strerror(err));
	goto out;
    }

    err = load_dynamic_libs(&sysinfo, 0);
    if (err)
	goto out;

    if (!command_file) {
	FILE *tf;
	command_file = malloc(strlen(BASE_CONF_STR) + 6 + strlen(sysinfo.name));
	if (!command_file) {
	    fprintf(stderr, "Out of memory\n");
	    goto out;
	}
	strcpy(command_file, BASE_CONF_STR);
	strcat(command_file, "/");
	strcat(command_file, sysinfo.name);
	strcat(command_file, ".emu");
	tf = fopen(command_file, "r");
	if (!tf) {
	    free(command_file);
	    command_file = NULL;
	} else {
	    fclose(tf);
	}
    }

    if (command_file)
	read_command_file(&stdio_console.out, data.emu, command_file);

    if (command_string)
	ipmi_emu_cmd(&stdio_console.out, data.emu, command_string);

    if (!sysinfo.bmc_ipmb || !sysinfo.ipmb_addrs[sysinfo.bmc_ipmb]) {
	sysinfo.log(&sysinfo, SETUP_ERROR, NULL,
		    "No bmc_ipmb specified or configured.");
	goto out;
    }

    sysinfo.console_fd = -1;
    if (sysinfo.console_addr_len) {
	int nfd;
	int val;

	nfd = socket(sysinfo.console_addr.s_ipsock.s_addr.sa_family,
		     SOCK_STREAM, IPPROTO_TCP);
	if (nfd == -1) {
	    perror("Console socket open");
	    goto out;
	}
	err = bind(nfd, (struct sockaddr *) &sysinfo.console_addr,
		   sysinfo.console_addr_len);
	if (err) {
	    perror("bind to console socket");
	    goto out;
	}
	err = listen(nfd, 1);
	if (err == -1) {
	    perror("listen to console socket");
	    goto out;
	}
	val = 1;
	err = setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR,
			 (char *)&val, sizeof(val));
	if (err) {
	    perror("console setsockopt reuseaddr");
	    goto out;
	}
	sysinfo.console_fd = nfd;

	err = data.os_hnd->add_fd_to_wait_for(data.os_hnd, nfd,
					      console_bind_ready, &data,
					      NULL, &conid);
	if (err) {
	    fprintf(stderr, "Unable to add console wait: 0x%x\n", err);
	    goto out;
	}
    }

    if (!nostdio) {
	init_term();

	err = write(1, "> ", 2);
	err = data.os_hnd->add_fd_to_wait_for(data.os_hnd, 0,
					      user_data_ready, &stdio_console,
					      NULL, &stdio_console.conid);
	if (err) {
	    fprintf(stderr, "Unable to add input wait: 0x%x\n", err);
	    goto out;
	}
    }

    post_init_dynamic_libs(&sysinfo);

    act.sa_handler = shutdown_handler;
    act.sa_flags = SA_RESETHAND;
    for (i = 0; shutdown_sigs[i]; i++) {
	err = sigaction(shutdown_sigs[i], &act, NULL);
	if (err) {
	    fprintf(stderr, "Unable to register shutdown signal %d: %s\n",
		    shutdown_sigs[i], strerror(errno));
	}
    }

    tv.tv_sec = 1;
    tv.tv_usec = 0;
    err = data.os_hnd->start_timer(data.os_hnd, data.timer, &tv, tick, &data);
    if (err) {
	fprintf(stderr, "Unable to start timer: 0x%x\n", err);
	goto out;
    }

    data.os_hnd->operation_loop(data.os_hnd);
    rv = 0;
  out:
    shutdown_handler(0);
    exit(rv);
}
Exemplo n.º 13
0
int
read_config(sys_data_t *sys,
	    char       *config_file,
	    int        print_version)
{
    FILE         *f = fopen(config_file, "r");
    int          line;
    unsigned int val;
    char         buf[MAX_CONFIG_LINE];
    const char   *tok;
    char         *tokptr;
    int          err = 0;
    const char   *errstr;

    if (!f) {
	fprintf(stderr, "Unable to open configuration file '%s'\n",
		config_file);
	return -1;
    }

    line = 0;
    while (fgets(buf, sizeof(buf), f) != NULL) {
	line++;

	tok = mystrtok(buf, " \t\n", &tokptr);
	if (!tok || (tok[0] == '#'))
	    continue;

	if (strcmp(tok, "define") == 0) {
	    const char *varname, *value;

	    varname = mystrtok(NULL, " \t\n", &tokptr);
	    if (!varname) {
		err = EINVAL;
		errstr = "No variable supplied for define";
		goto next;
	    }
	    err = get_delim_str(&tokptr, &value, &errstr);
	    if (err)
		goto next;
	    err = add_variable(varname, value);
	    if (err) {
		err = ENOMEM;
		errstr = "Out of memory";
		goto next;
	    }
	} else if (strcmp(tok, "loadlib") == 0) {
	    const char *library = NULL, *initstr = NULL;
	    struct dliblist *dlib, *dlibp;

	    err = get_delim_str(&tokptr, &library, &errstr);
	    if (!err)
		err = get_delim_str(&tokptr, &initstr, &errstr);
	    if (!err) {
		dlib = malloc(sizeof(*dlib));
		if (!dlib) {
		    err = ENOMEM;
		    errstr = "Out of memory";
		} else {
		    dlib->file = library;
		    dlib->init = initstr;
		    dlib->next = NULL;
		    if (!dlibs) {
			dlibs = dlib;
		    } else {
			dlibp = dlibs;
			while (dlibp->next)
			    dlibp = dlibp->next;
			dlibp->next = dlib;
		    }
		}
	    }
	    if (err) {
		if (library)
		    free((char *) library);
		if (initstr)
		    free((char *) initstr);
	    }
	    goto next;
	}

	if (print_version)
	    goto next;

	if (strcmp(tok, "startlan") == 0) {
	    err = get_uint(&tokptr, &val, &errstr);
	    if (!err && (val >= IPMI_MAX_CHANNELS)) {
		err = -1;
		errstr = "Channel number out of range";
	    }
	    if (!err) {
		err = lanserv_read_config(sys, f, &line, val);
	    }
	} else if (strcmp(tok, "user") == 0) {
	    err = get_user(&tokptr, sys, &errstr);
	} else if (strcmp(tok, "serial") == 0) {
	    err = serserv_read_config(&tokptr, sys, &errstr);
	} else if (strcmp(tok, "sol") == 0) {
	    err = sol_read_config(&tokptr, sys, &errstr);
	} else if (strcmp(tok, "chassis_control") == 0) {
	    const char *prog;
	    err = get_delim_str(&tokptr, &prog, &errstr);
	    if (!err)
		ipmi_set_chassis_control_prog(sys->mc, prog);
	} else if (strcmp(tok, "name") == 0) {
	    err = get_delim_str(&tokptr, &sys->name, &errstr);
	} else if (strcmp(tok, "startcmd") == 0) {
	    err = get_delim_str(&tokptr, &sys->startcmd->startcmd, &errstr);
	} else if (strcmp(tok, "startnow") == 0) {
	    err = get_bool(&tokptr, &sys->startcmd->startnow, &errstr);
	} else if (strcmp(tok, "poweroff_wait") == 0) {
	    err = get_uint(&tokptr, &sys->startcmd->poweroff_wait_time,
			   &errstr);
	} else if (strcmp(tok, "kill_wait") == 0) {
	    err = get_uint(&tokptr, &sys->startcmd->kill_wait_time, &errstr);
	} else if (strcmp(tok, "set_working_mc") == 0) {
	    unsigned char ipmb;
	    err = get_uchar(&tokptr, &ipmb, &errstr);
	    if (!err) {
		lmc_data_t *mc;
		err = ipmi_mc_alloc_unconfigured(sys, ipmb, &mc);
		if (err == ENOMEM) {
		    errstr = "Out of memory";
		    err = -1;
		} else if (err) {
		    errstr = "Invalid IPMB specified";
		    err = -1;
		} else {
		    sys->mc = mc;
		    sys->cusers = ipmi_mc_get_users(mc);
		    sys->chan_set = ipmi_mc_get_channelset(mc);
		    sys->cpef = ipmi_mc_get_pef(mc);
		    sys->startcmd = ipmi_mc_get_startcmdinfo(mc);
		    sys->sol = ipmi_mc_get_sol(mc);
		}
	    }
	} else if (strcmp(tok, "console") == 0) {
	    err = get_sock_addr(&tokptr,
				&sys->console_addr, &sys->console_addr_len,
				NULL, SOCK_STREAM, &errstr);
	} else {
	    errstr = "Invalid configuration option";
	    err = -1;
	}

      next:
	if (err) {
	    fprintf(stderr, "Error on line %d: %s\n", line, errstr);
	    break;
	}
    }

    fclose(f);

    if (print_version)
	load_dynamic_libs(sys, print_version);

    return err;
}