int stonithd_signoff(void) { struct ha_msg * request; gboolean connected = TRUE; if (chan == NULL || chan->ch_status != IPC_CONNECT) { connected = FALSE; } else if (cbchan == NULL || cbchan->ch_status != IPC_CONNECT) { connected = FALSE; } if (!connected) { stdlib_log(LOG_NOTICE, "Not currently connected."); goto bail; } if ( (request = create_basic_reqmsg_fields(ST_SIGNOFF)) == NULL) { stdlib_log(LOG_ERR, "Couldn't create signoff message!"); goto bail; } /* Send the signoff request message */ if (msg2ipcchan(request, chan) != HA_OK) { ZAPMSG(request); stdlib_log(LOG_ERR, "Control channel dead - can't send signoff message"); goto bail; } /* waiting for the output to finish */ chan_waitout_timeout(chan, DEFAULT_TIMEOUT); ZAPMSG(request); bail: if (NULL != chan) { chan->ops->destroy(chan); chan = NULL; } if (NULL != cbchan) { cbchan->ops->destroy(cbchan); cbchan = NULL; } return ST_OK; }
static int authenticate_with_cookie(IPC_Channel *chan, cl_uuid_t *cookie) { struct ha_msg * request; struct ha_msg * reply; assert(chan != NULL); assert(cookie != NULL); if (!(request = create_basic_reqmsg_fields(ST_SIGNON))) { return ST_FAIL; } if (ha_msg_adduuid(request, F_STONITHD_COOKIE, cookie) != HA_OK) { stdlib_log(LOG_ERR, "cannot add field to ha_msg."); ZAPMSG(request); return ST_FAIL; } /* Send request/read response */ if (send_request(chan, request, DEFAULT_TIMEOUT) != ST_OK) { ZAPMSG(request); return ST_FAIL; } ZAPMSG(request); if (!(reply = recv_response(chan, DEFAULT_TIMEOUT))) { return ST_FAIL; } /* Are we signed on this time? */ if ( TRUE == is_expected_msg(reply, F_STONITHD_TYPE, ST_APIRPL, F_STONITHD_APIRPL, ST_RSIGNON, TRUE) ) { if ( !STRNCMP_CONST( cl_get_string(reply,F_STONITHD_APIRET), ST_APIOK) ) { ZAPMSG(reply); return ST_OK; } } ZAPMSG(reply); return ST_FAIL; }
/* Temporarily just handle string hashtable correctly */ int ha_msg_addhash(struct ha_msg * msg, const char * name, GHashTable * htable) { struct ha_msg * msg_tmp = NULL; if (msg == NULL || htable == NULL ) { stdmsg_log(LOG_ERR, "ha_msg_addhash: NULL parameter pointers."); return HA_FAIL; } if ((msg_tmp = hashtable_to_hamsg(htable)) == NULL ) { stdmsg_log(LOG_ERR, "hashtable_to_hamsg failed."); return HA_FAIL; } if ( ha_msg_addstruct(msg, name, msg_tmp) != HA_OK ) { stdmsg_log(LOG_ERR, "ha_msg_addhash: ha_msg_addstruct failed."); ZAPMSG(msg_tmp); return HA_FAIL; } ZAPMSG(msg_tmp); return HA_OK; }
static struct ha_msg * create_basic_reqmsg_fields(const char * apitype) { struct ha_msg * msg = NULL; if ((msg = ha_msg_new(4)) == NULL) { stdlib_log(LOG_ERR, "create_basic_msg_fields:out of memory."); return NULL; } /* important error check client name length */ if ( (ha_msg_add(msg, F_STONITHD_TYPE, ST_APIREQ ) != HA_OK ) ||( ha_msg_add(msg, F_STONITHD_APIREQ, apitype) != HA_OK) ||( ha_msg_add(msg, F_STONITHD_CNAME, CLIENT_NAME) != HA_OK) ||( ha_msg_add_int(msg, F_STONITHD_CPID, CLIENT_PID) != HA_OK) ) { stdlib_log(LOG_ERR, "create_basic_msg_fields: " "cannot add field to ha_msg."); ZAPMSG(msg); } return msg; }
int stonithd_list_stonith_types(GList ** types) { int rc = ST_FAIL; struct ha_msg * request, * reply; const char * tmpstr; if ( !signed_on(chan) ) { stdlib_log(LOG_ERR, "not signed on"); return ST_FAIL; } if ( (request = create_basic_reqmsg_fields(ST_LTYPES)) == NULL) { return ST_FAIL; } /* Send the request message */ if (msg2ipcchan(request, chan) != HA_OK) { ZAPMSG(request); stdlib_log(LOG_ERR, "can't send stonithRA message to IPC"); return ST_FAIL; } /* waiting for the output to finish */ chan_waitout_timeout(chan, DEFAULT_TIMEOUT); ZAPMSG(request); /* Read the reply... */ stdlib_log(LOG_DEBUG, "waiting for the reply to list stonith types."); if ( IPC_OK != chan_waitin_timeout(chan, DEFAULT_TIMEOUT) ) { stdlib_log(LOG_ERR, "%s:%d: chan_waitin failed." , __FUNCTION__, __LINE__); return ST_FAIL; } if ( (reply = msgfromIPC_noauth(chan)) == NULL ) { stdlib_log(LOG_ERR, "stonithd_list_stonith_types: " "failed to fetch reply."); return ST_FAIL; } *types = NULL; if ( TRUE == is_expected_msg(reply, F_STONITHD_TYPE, ST_APIRPL, F_STONITHD_APIRPL, ST_RLTYPES, TRUE) ) { if ( ((tmpstr = cl_get_string(reply, F_STONITHD_APIRET)) != NULL) && (STRNCMP_CONST(tmpstr, ST_APIOK) == 0) ) { int i; int len=cl_msg_list_length(reply, F_STONITHD_STTYPES); if ( len < 0 ) { stdlib_log(LOG_ERR, "Not field to list stonith " "types."); } else { for (i = 0; i < len; i++) { tmpstr = cl_msg_list_nth_data(reply, F_STONITHD_STTYPES, i); if( tmpstr ) { *types = g_list_append(*types, g_strdup(tmpstr)); } } stdlib_log(LOG_DEBUG, "got stonith types."); rc = ST_OK; } } else { stdlib_log(LOG_DEBUG, "failed to get stonith types."); } } else { stdlib_log(LOG_DEBUG, "stonithd_list_stonith_types: " "Got an unexpected message."); } ZAPMSG(reply); return rc; }
int stonithd_virtual_stonithRA_ops( stonithRA_ops_t * op, int * call_id) { int rc = ST_FAIL; struct ha_msg * request, * reply; const char * tmpstr; if (op == NULL) { stdlib_log(LOG_ERR, "stonithd_virtual_stonithRA_ops: op==NULL"); return ST_FAIL; } if (call_id == NULL) { stdlib_log(LOG_ERR, "stonithd_stonithd_stonithRA_ops: " "call_id==NULL"); return ST_FAIL; } if ( !signed_on(chan) ) { stdlib_log(LOG_ERR, "not signed on"); return ST_FAIL; } if ( (request = create_basic_reqmsg_fields(ST_RAOP)) == NULL) { return ST_FAIL; } if ( (ha_msg_add(request, F_STONITHD_RSCID, op->rsc_id) != HA_OK) ||(ha_msg_add(request, F_STONITHD_RAOPTYPE, op->op_type) != HA_OK) ||(ha_msg_add(request, F_STONITHD_RANAME, op->ra_name) != HA_OK) ||(ha_msg_add_int(request, F_STONITHD_TIMEOUT, op->timeout) != HA_OK) ||(ha_msg_addhash(request, F_STONITHD_PARAMS, op->params) != HA_OK) ) { stdlib_log(LOG_ERR, "stonithd_virtual_stonithRA_ops: " "cannot add field to ha_msg."); ZAPMSG(request); return ST_FAIL; } /* Send the request message */ if (msg2ipcchan(request, chan) != HA_OK) { ZAPMSG(request); stdlib_log(LOG_ERR, "can't send stonithRA message to IPC"); return ST_FAIL; } /* waiting for the output to finish */ chan_waitout_timeout(chan, DEFAULT_TIMEOUT); ZAPMSG(request); /* Read the reply... */ stdlib_log(LOG_DEBUG, "waiting for the stonithRA reply msg."); if ( IPC_OK != chan_waitin_timeout(chan, DEFAULT_TIMEOUT) ) { stdlib_log(LOG_ERR, "%s:%d: waitin failed." , __FUNCTION__, __LINE__); return ST_FAIL; } if ( (reply = msgfromIPC_noauth(chan)) == NULL ) { stdlib_log(LOG_ERR, "stonithd_virtual_stonithRA_ops: " "failed to fetch reply"); return ST_FAIL; } if ( FALSE == is_expected_msg(reply, F_STONITHD_TYPE, ST_APIRPL, F_STONITHD_APIRPL, ST_RRAOP, TRUE) ) { ZAPMSG(reply); /* avoid to zap the msg ? */ stdlib_log(LOG_WARNING, "stonithd_virtual_stonithRA_ops: " "got an unexpected message"); return ST_FAIL; } if ( ((tmpstr = cl_get_string(reply, F_STONITHD_APIRET)) != NULL) && (STRNCMP_CONST(tmpstr, ST_APIOK) == 0) ) { int tmpint; if ( ha_msg_value_int(reply, F_STONITHD_CALLID, &tmpint) == HA_OK ) { *call_id = tmpint; rc = ST_OK; stdlib_log(LOG_DEBUG, "a stonith RA operation queue " \ "to run, call_id=%d.", *call_id); } else { stdlib_log(LOG_ERR, "no return call_id in reply"); rc = ST_FAIL; } } else { stdlib_log(LOG_WARNING, "failed to do the RA op."); rc = ST_FAIL; * call_id = -1; } ZAPMSG(reply); return rc; }
int stonithd_receive_ops_result(gboolean blocking) { struct ha_msg* reply = NULL; const char *reply_type; int rc = ST_OK; stdlib_log(LOG_DEBUG, "stonithd_receive_ops_result: begin"); /* If there is no msg ready and none blocking mode, then return */ if ((stonithd_op_result_ready() == FALSE) && (blocking == FALSE)) { stdlib_log(LOG_DEBUG, "stonithd_receive_ops_result: " "no result available."); return ST_OK; } if (stonithd_op_result_ready() == FALSE) { /* at that time, blocking must be TRUE */ rc = cbchan->ops->waitin(cbchan); if (IPC_OK != rc) { if (cbchan->ch_status == IPC_DISCONNECT) { stdlib_log(LOG_INFO, "%s:%d: disconnected", __FUNCTION__, __LINE__); } else if (IPC_INTR == rc) { stdlib_log(LOG_INFO, "%s:%d: waitin interrupted", __FUNCTION__, __LINE__); } else { stdlib_log(LOG_WARNING, "%s:%d: waitin failed: %d", __FUNCTION__, __LINE__,rc); } return ST_FAIL; } } reply = msgfromIPC_noauth(cbchan); reply_type = cl_get_string(reply, F_STONITHD_APIRPL); if ( !is_expected_msg(reply, F_STONITHD_TYPE, ST_APIRPL, F_STONITHD_APIRPL, reply_type, TRUE)) { ZAPMSG(reply); stdlib_log(LOG_DEBUG, "%s:%d: " "got an unexpected message", __FUNCTION__, __LINE__); return ST_FAIL; } if( !strcmp(reply_type, ST_STRET) ) { stonith_ops_t *st_op = NULL; /* handle the stonith op result message */ if( !(st_op = g_new(stonith_ops_t, 1)) ) { stdlib_log(LOG_ERR, "out of memory"); return ST_FAIL; } st_op->node_uuid = NULL; st_op->private_data = NULL; st_get_int_value(reply, F_STONITHD_OPTYPE, (int*)&st_op->optype); st_save_string(reply, F_STONITHD_NODE, st_op->node_name); st_save_string(reply, F_STONITHD_NODE_UUID, st_op->node_uuid); st_get_int_value(reply, F_STONITHD_TIMEOUT, &st_op->timeout); st_get_int_value(reply, F_STONITHD_CALLID, &st_op->call_id); st_get_int_value(reply, F_STONITHD_FRC, (int*)&st_op->op_result); st_save_string(reply, F_STONITHD_NLIST, st_op->node_list); st_save_string(reply, F_STONITHD_PDATA, st_op->private_data); if (stonith_ops_cb != NULL) { stonith_ops_cb(st_op); } free_stonith_ops_t(st_op); } else if( !strcmp(reply_type, ST_RAOPRET) ) { stonithRA_ops_t *ra_op = NULL; /* handle the stonithRA op result message */ if( !(ra_op = g_new(stonithRA_ops_t, 1)) ) { stdlib_log(LOG_ERR, "out of memory"); return ST_FAIL; } st_save_string(reply, F_STONITHD_RSCID, ra_op->rsc_id); st_save_string(reply, F_STONITHD_RAOPTYPE, ra_op->op_type); st_save_string(reply, F_STONITHD_RANAME, ra_op->ra_name); st_get_hashtable(reply, F_STONITHD_PARAMS, ra_op->params); st_get_int_value(reply, F_STONITHD_CALLID, &ra_op->call_id); st_get_int_value(reply, F_STONITHD_FRC, &ra_op->op_result); /* if ( rc == ST_OK && stonithRA_ops_cb != NULL) */ if ( stonithRA_ops_cb ) { stonithRA_ops_cb(ra_op, stonithRA_ops_cb_private_data); } free_stonithRA_ops_t(ra_op); } else { stdlib_log(LOG_DEBUG, "%s:%d: " "got an unexpected message", __FUNCTION__, __LINE__); rc = ST_FAIL; } ZAPMSG(reply); return rc; }
int stonithd_node_fence(stonith_ops_t * op) { int rc = ST_FAIL; struct ha_msg *request, *reply; if (op == NULL) { stdlib_log(LOG_ERR, "stonithd_node_fence: op==NULL"); goto out; } if (!signed_on(chan)) { stdlib_log(LOG_NOTICE, "not signed on"); goto out; } if (!(request = create_basic_reqmsg_fields(ST_STONITH))) { stdlib_log(LOG_ERR, "stonithd_node_fence: " "message creation failed."); goto out; } if (ha_msg_add_int(request, F_STONITHD_OPTYPE, op->optype) != HA_OK) { stdlib_log(LOG_ERR, "stonithd_node_fence: " "cannot add optype field to ha_msg."); goto out; } if (ha_msg_add(request, F_STONITHD_NODE, op->node_name ) != HA_OK) { stdlib_log(LOG_ERR, "stonithd_node_fence: " "cannot add node_name field to ha_msg."); goto out; } if (op->node_uuid == NULL || (ha_msg_add(request, F_STONITHD_NODE_UUID, op->node_uuid) != HA_OK)) { stdlib_log(LOG_ERR, "stonithd_node_fence: " "cannot add node_uuid field to ha_msg."); goto out; } if (ha_msg_add_int(request, F_STONITHD_TIMEOUT, op->timeout) != HA_OK) { stdlib_log(LOG_ERR, "stonithd_node_fence: " "cannot add timeout field to ha_msg."); goto out; } if (op->private_data == NULL || (ha_msg_add(request, F_STONITHD_PDATA, op->private_data) != HA_OK)) { stdlib_log(LOG_ERR, "stonithd_node_fence: " "cannot add private_data field to ha_msg."); goto out; } /* Send the stonith request message */ if (msg2ipcchan(request, chan) != HA_OK) { stdlib_log(LOG_ERR , "failed to send stonith request to stonithd"); goto out; } /* waiting for the output to finish */ chan_waitout_timeout(chan, DEFAULT_TIMEOUT); /* Read the reply... */ stdlib_log(LOG_DEBUG, "waiting for the stonith reply msg."); if ( IPC_OK != chan_waitin_timeout(chan, DEFAULT_TIMEOUT) ) { stdlib_log(LOG_ERR, "%s:%d: waitin failed." , __FUNCTION__, __LINE__); goto out; } if ( (reply = msgfromIPC_noauth(chan)) == NULL ) { stdlib_log(LOG_ERR, "stonithd_node_fence: fail to fetch reply"); goto out; } if ( TRUE == is_expected_msg(reply, F_STONITHD_TYPE, ST_APIRPL, F_STONITHD_APIRPL, ST_RSTONITH, TRUE) ) { if( !STRNCMP_CONST( cl_get_string(reply,F_STONITHD_APIRET), ST_APIOK) ) { rc = ST_OK; stdlib_log(LOG_DEBUG, "%s:%d: %s" , __FUNCTION__, __LINE__ , "stonithd's synchronous answer is ST_APIOK"); } else { stdlib_log(LOG_ERR, "%s:%d: %s" , __FUNCTION__, __LINE__ , "stonithd's synchronous answer is ST_APIFAIL"); } } else { stdlib_log(LOG_ERR, "stonithd_node_fence: " "Got an unexpected message."); /* Need to handle in other way? */ } out: ZAPMSG(reply); ZAPMSG(request); return rc; }
int stonithd_signon(const char * client_name) { int rc = ST_FAIL; char path[] = IPC_PATH_ATTR; char sock[] = STONITHD_SOCK; char cbsock[] = STONITHD_CALLBACK_SOCK; struct ha_msg * request; struct ha_msg * reply; GHashTable * wchanattrs; uid_t my_euid; gid_t my_egid; const char * tmpstr; int rc_tmp; gboolean connected = TRUE; cl_uuid_t cookie, *cptr = NULL; if (chan == NULL || chan->ch_status != IPC_CONNECT) { connected = FALSE; } else if (cbchan == NULL || cbchan->ch_status != IPC_CONNECT) { connected = FALSE; } if(!connected) { /* cleanup */ if (NULL != chan) { chan->ops->destroy(chan); chan = NULL; } if (NULL != cbchan) { cbchan->ops->destroy(cbchan); cbchan = NULL; } stdlib_log(LOG_DEBUG, "stonithd_signon: creating connection"); wchanattrs = g_hash_table_new(g_str_hash, g_str_equal); g_hash_table_insert(wchanattrs, path, sock); /* Connect to the stonith deamon */ chan = ipc_channel_constructor(IPC_ANYTYPE, wchanattrs); g_hash_table_destroy(wchanattrs); if (chan == NULL) { stdlib_log(LOG_ERR, "stonithd_signon: Can't connect " " to stonithd"); rc = ST_FAIL; goto end; } if (chan->ops->initiate_connection(chan) != IPC_OK) { stdlib_log(LOG_ERR, "stonithd_signon: Can't initiate " "connection to stonithd"); rc = ST_FAIL; goto end; } } CLIENT_PID = getpid(); snprintf(CLIENT_PID_STR, sizeof(CLIENT_PID_STR), "%d", CLIENT_PID); if ( client_name != NULL ) { CLIENT_NAME = client_name; } else { CLIENT_NAME = CLIENT_PID_STR; } if ( (request = create_basic_reqmsg_fields(ST_SIGNON)) == NULL) { rc = ST_FAIL; goto end; } /* important error check client name length */ my_euid = geteuid(); my_egid = getegid(); if ( ( ha_msg_add_int(request, F_STONITHD_CEUID, my_euid) != HA_OK ) ||( ha_msg_add_int(request, F_STONITHD_CEGID, my_egid) != HA_OK ) ||( ha_msg_add(request, F_STONITHD_COOKIE, "") != HA_OK ) ) { stdlib_log(LOG_ERR, "stonithd_signon: " "cannot add field to ha_msg."); ZAPMSG(request); rc = ST_FAIL; goto end; } stdlib_log(LOG_DEBUG, "sending out the signon msg."); /* Send the registration request message */ if (msg2ipcchan(request, chan) != HA_OK) { ZAPMSG(request); stdlib_log(LOG_ERR, "can't send signon message to IPC"); rc = ST_FAIL; goto end; } /* waiting for the output to finish */ do { rc_tmp= chan_waitout_timeout(chan, DEFAULT_TIMEOUT); } while (rc_tmp == IPC_INTR); ZAPMSG(request); if (IPC_OK != rc_tmp) { stdlib_log(LOG_ERR, "%s:%d: waitout failed." , __FUNCTION__, __LINE__); rc = ST_FAIL; goto end; } /* Read the reply... */ if ( IPC_OK != chan_waitin_timeout(chan, DEFAULT_TIMEOUT) ) { stdlib_log(LOG_ERR, "%s:%d: waitin failed." , __FUNCTION__, __LINE__); rc = ST_FAIL; goto end; } if ( (reply = msgfromIPC_noauth(chan)) == NULL ) { stdlib_log(LOG_ERR, "stonithd_signon: failed to fetch reply."); rc = ST_FAIL; goto end; } if ( TRUE == is_expected_msg(reply, F_STONITHD_TYPE, ST_APIRPL, F_STONITHD_APIRPL, ST_RSIGNON, TRUE) ) { if ( ((tmpstr=cl_get_string(reply, F_STONITHD_APIRET)) != NULL) && (STRNCMP_CONST(tmpstr, ST_APIOK) == 0) ) { rc = ST_OK; stdlib_log(LOG_DEBUG, "signed on to stonithd."); /* get cookie if any */ if( cl_get_uuid(reply, F_STONITHD_COOKIE, &cookie) == HA_OK ) { cptr = &cookie; } } else { stdlib_log(LOG_WARNING, "failed to signon to the " "stonithd."); } } else { stdlib_log(LOG_ERR, "stonithd_signon: " "Got an unexpected message."); } ZAPMSG(reply); if (ST_OK != rc) { /* Something wrong when try to sign on to stonithd */ goto end; } /* Connect to the stonith deamon via callback channel */ wchanattrs = g_hash_table_new(g_str_hash, g_str_equal); g_hash_table_insert(wchanattrs, path, cbsock); cbchan = ipc_channel_constructor(IPC_ANYTYPE, wchanattrs); g_hash_table_destroy(wchanattrs); if (cbchan == NULL) { stdlib_log(LOG_ERR, "stonithd_signon: Can't construct " "callback channel to stonithd."); rc = ST_FAIL; goto end; } if (cbchan->ops->initiate_connection(cbchan) != IPC_OK) { stdlib_log(LOG_ERR, "stonithd_signon: Can't initiate " "connection with the callback channel"); rc = ST_FAIL; goto end; } if ( (reply = msgfromIPC_noauth(cbchan)) == NULL ) { stdlib_log(LOG_ERR, "%s:%d: failed to fetch reply via the " " callback channel" , __FUNCTION__, __LINE__); rc = ST_FAIL; goto end; } if ( TRUE == is_expected_msg(reply, F_STONITHD_TYPE, ST_APIRPL, F_STONITHD_APIRPL, ST_RSIGNON, TRUE) ) { tmpstr=cl_get_string(reply, F_STONITHD_APIRET); if ( !STRNCMP_CONST(tmpstr, ST_APIOK) ) { /* * If the server directly authenticates us (probably * via pid-auth), go ahead. */ stdlib_log(LOG_DEBUG, "%s:%d: Got a good signon reply " "via the callback channel." , __FUNCTION__, __LINE__); } else if ( !STRNCMP_CONST(tmpstr, ST_COOKIE) ) { /* * If the server asks for a cookie to identify myself, * initiate cookie authentication. */ if (cptr == NULL) { stdlib_log(LOG_ERR, "server requested cookie auth on " "the callback channel, but it didn't " "provide the cookie on the main channel."); rc = ST_FAIL; } else { rc = authenticate_with_cookie(cbchan, cptr); } } else { /* Unknown response. */ rc = ST_FAIL; stdlib_log(LOG_ERR, "%s:%d: Got a bad signon reply " "via the callback channel." , __FUNCTION__, __LINE__); } } else { rc = ST_FAIL; stdlib_log(LOG_ERR, "stonithd_signon: " "Got an unexpected message via the callback chan."); } ZAPMSG(reply); end: if (ST_OK != rc) { /* Something wrong when confirm via callback channel */ stonithd_signoff(); } return rc; }