/* * updown_event_setup * * updown event module setup function. */ static int updown_event_setup(void) { if (!(node_states = hash_create(UPDOWN_HASH_SIZE, (hash_key_f)hash_key_string, (hash_cmp_f)strcmp, (hash_del_f)free))) { CEREBRO_ERR(("hash_create: %s", strerror(errno))); goto cleanup; } if (!(node_states_nodenames = list_create((ListDelF)free))) { CEREBRO_ERR(("list_create: %s", strerror(errno))); goto cleanup; } return 0; cleanup: if (node_states) { hash_destroy(node_states); node_states = NULL; } if (node_states_nodenames) { list_destroy(node_states_nodenames); node_states_nodenames = NULL; } return -1; }
/* * cerebro_get_loadavgs * * Read load averages */ int cerebro_metric_get_loadavgs(float *loadavg1, float *loadavg5, float *loadavg15) { int len, fd = -1; char buf[LOADAVG_BUFLEN]; struct timeval now; int rv = -1; if (gettimeofday(&now, NULL) < 0) { CEREBRO_ERR(("gettimeofday: %s", strerror(errno))); goto cleanup; } if ((now.tv_sec - last_read) > LOADVAG_CACHETIMEOUT) { if ((fd = open(LOADAVG_FILE, O_RDONLY, 0)) < 0) { CEREBRO_ERR(("open: %s", strerror(errno))); goto cleanup; } memset(buf, '\0', LOADAVG_BUFLEN); if ((len = read(fd, buf, LOADAVG_BUFLEN)) < 0) { CEREBRO_ERR(("read: %s", strerror(errno))); goto cleanup; } if (sscanf(buf, "%f %f %f", &cache_loadavg1, &cache_loadavg5, &cache_loadavg15) != 3) { CEREBRO_DBG(("loadavg file parse error")); goto cleanup; } last_read = now.tv_sec; } if (loadavg1) *loadavg1 = cache_loadavg1; if (loadavg5) *loadavg5 = cache_loadavg5; if (loadavg15) *loadavg15 = cache_loadavg15; rv = 0; cleanup: /* ignore potential error, just return result */ if (fd >= 0) close(fd); return rv; }
/* * _event_server_err_only_response * * respond to the event_server_request with an error * * Return 0 on success, -1 on error */ static int _event_server_err_only_response(int fd, int32_t version, u_int32_t err_code) { struct cerebro_event_server_response res; char buf[CEREBRO_MAX_PACKET_LEN]; int res_len; assert(fd >= 0 && err_code >= CEREBRO_EVENT_SERVER_PROTOCOL_ERR_SUCCESS && err_code <= CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR); memset(&res, '\0', CEREBRO_EVENT_SERVER_RESPONSE_LEN); res.version = version; res.err_code = err_code; res.end = CEREBRO_EVENT_SERVER_PROTOCOL_IS_LAST_RESPONSE; if ((res_len = _event_server_response_marshall(&res, buf, CEREBRO_MAX_PACKET_LEN)) < 0) return -1; if (fd_write_n(fd, buf, res_len) < 0) { CEREBRO_ERR(("fd_write_n: %s", strerror(errno))); return -1; } return 0; }
/* * _readline * * read a line from the hostsfile. Buffer guaranteed to be null * terminated. * * - fd - file descriptor to read from * - buf - buffer pointer * - buflen - buffer length * * Return amount of data read into the buffer, -1 on error */ static int _readline(int fd, char *buf, unsigned int buflen) { int len; if (fd <= 0 || !buf || !buflen) { CEREBRO_DBG(("invalid parameters")); return -1; } if ((len = fd_read_line(fd, buf, buflen)) < 0) { CEREBRO_ERR(("fd_read_line: %s", strerror(errno))); return -1; } /* buflen - 1 b/c fd_read_line guarantees null termination */ if (len >= (buflen-1)) { CEREBRO_DBG(("fd_read_line: line truncation")); return -1; } return len; }
/* * _respond_with_event_names * * Return 0 on success, -1 on error */ static void * _respond_with_event_names(void *arg) { struct cerebrod_event_names_response_data enr; List responses = NULL; int fd; assert(arg); fd = *((int *)arg); if (!event_names) goto end_response; if (!List_count(event_names)) goto end_response; if (!(responses = list_create((ListDelF)free))) { CEREBRO_ERR(("list_create: %s", strerror(errno))); _event_server_err_only_response(fd, CEREBRO_EVENT_SERVER_PROTOCOL_VERSION, CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR); goto cleanup; } enr.fd = fd; enr.responses = responses; /* Event names is not changeable - so no need for a lock */ if (list_for_each(event_names, _event_names_callback, &enr) < 0) { _event_server_err_only_response(fd, CEREBRO_EVENT_SERVER_PROTOCOL_VERSION, CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR); goto cleanup; } if (_send_event_names(fd, responses) < 0) { _event_server_err_only_response(fd, CEREBRO_EVENT_SERVER_PROTOCOL_VERSION, CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR); goto cleanup; } end_response: if (_send_event_names_end_response(fd) < 0) goto cleanup; cleanup: if (responses) list_destroy(responses); Free(arg); /* ignore potential error, we're done sendin */ close(fd); return NULL; }
/* * _event_server_setup_socket * * Create and setup the server socket. Do not use wrappers in this * function. We want to give the server additional chances to * "survive" an error condition. * * Returns file descriptor on success, -1 on error * * Note: num parameter unused in this function, here only to match function prototype */ static int _event_server_setup_socket(int num) { struct sockaddr_in addr; int fd, optval = 1; if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { CEREBRO_ERR(("socket: %s", strerror(errno))); goto cleanup; } /* For quick start/restart */ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int)) < 0) { CEREBRO_ERR(("setsockopt: %s", strerror(errno))); goto cleanup; } memset(&addr, '\0', sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = htons(conf.event_server_port); addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { CEREBRO_ERR(("bind: %s", strerror(errno))); goto cleanup; } if (listen(fd, CEREBROD_EVENT_SERVER_BACKLOG) < 0) { CEREBRO_ERR(("listen: %s", strerror(errno))); goto cleanup; } return fd; cleanup: /* ignore potential error, just return error */ close(fd); return -1; }
/* * _create_entry * * Create an entry in the node_states hash */ static int * _create_entry(const char *nodename) { char *nodePtr = NULL; int *state = NULL; if (!(state = (int *)malloc(sizeof(int)))) { CEREBRO_ERR(("malloc: %s", strerror(errno))); goto cleanup; } if (!(nodePtr = (char *)malloc(CEREBRO_MAX_NODENAME_LEN + 1))) { CEREBRO_ERR(("malloc: %s", strerror(errno))); goto cleanup; } strncpy(nodePtr, nodename, CEREBRO_MAX_NODENAME_LEN); if (!list_append(node_states_nodenames, nodePtr)) { CEREBRO_DBG(("list_append: %s", strerror(errno))); goto cleanup; } if (!hash_insert(node_states, nodePtr, state)) { CEREBRO_DBG(("hash_insert: %s", strerror(errno))); goto cleanup; } *state = UPDOWN_EVENT_STATE_INIT; return state; cleanup: free(nodePtr); free(state); return NULL; }
/* * _event_names_callback * * Callback function to create event name responses * * Return 0 on success, -1 on error */ static int _event_names_callback(void *data, void *arg) { struct cerebrod_event_names_response_data *enr; struct cerebro_event_server_response *res = NULL; char *event_name; assert(data && arg); event_name = (char *)data; enr = (struct cerebrod_event_names_response_data *)arg; if (!(res = malloc(sizeof(struct cerebro_event_server_response)))) { CEREBRO_ERR(("malloc: %s", strerror(errno))); goto cleanup; } memset(res, '\0', sizeof(struct cerebro_event_server_response)); res->version = CEREBRO_EVENT_SERVER_PROTOCOL_VERSION; res->err_code = CEREBRO_EVENT_SERVER_PROTOCOL_ERR_SUCCESS; res->end = CEREBRO_EVENT_SERVER_PROTOCOL_IS_NOT_LAST_RESPONSE; /* strncpy, b/c terminating character not required */ strncpy(res->event_name, event_name, CEREBRO_MAX_EVENT_NAME_LEN); if (!list_append(enr->responses, res)) { CEREBRO_ERR(("list_append: %s", strerror(errno))); goto cleanup; } return 0; cleanup: if (res) free(res); return -1; }
/* * _create_event * * Create an event */ static struct cerebro_event * _create_event(const char *nodename, int state) { struct cerebro_event *event = NULL; if (!(event = (struct cerebro_event *)malloc(sizeof(struct cerebro_event)))) { CEREBRO_ERR(("malloc: %s", strerror(errno))); goto cleanup; } event->version = CEREBRO_EVENT_PROTOCOL_VERSION; event->err_code = CEREBRO_EVENT_SERVER_PROTOCOL_ERR_SUCCESS; strncpy(event->nodename, nodename, CEREBRO_MAX_NODENAME_LEN); strncpy(event->event_name, UPDOWN_EVENT_NAME, CEREBRO_MAX_EVENT_NAME_LEN); event->event_value_type = CEREBRO_DATA_VALUE_TYPE_INT32; event->event_value_len = sizeof(int32_t); if (!(event->event_value = malloc(sizeof(int32_t)))) { CEREBRO_ERR(("malloc: %s", strerror(errno))); goto cleanup; } *((int *)event->event_value) = state; return event; cleanup: if (event) { if (event->event_value) free(event->event_value); free(event); } return NULL; }
/* * bytesin_metric_get_metric_value * * bytesin metric module get_metric_value function */ static int bytesin_metric_get_metric_value(unsigned int *metric_value_type, unsigned int *metric_value_len, void **metric_value) { u_int64_t bytesinval; u_int64_t *bytesinptr = NULL; int rv = -1; if (!metric_value_type || !metric_value_len || !metric_value) { CEREBRO_DBG(("invalid parameters")); return -1; } if (cerebro_metric_get_network(&bytesinval, NULL, NULL, NULL, NULL, NULL) < 0) goto cleanup; if (!(bytesinptr = (u_int64_t *)malloc(sizeof(u_int64_t)))) { CEREBRO_ERR(("malloc: %s", strerror(errno))); goto cleanup; } *bytesinptr = bytesinval; *metric_value_type = CEREBRO_DATA_VALUE_TYPE_U_INT64; *metric_value_len = sizeof(u_int64_t); *metric_value = (void *)bytesinptr; rv = 0; cleanup: if (rv < 0 && bytesinptr) free(bytesinptr); return rv; }
/* * txerrs_metric_get_metric_value * * txerrs metric module get_metric_value function */ static int txerrs_metric_get_metric_value(unsigned int *metric_value_type, unsigned int *metric_value_len, void **metric_value) { u_int32_t txerrsval; u_int32_t *txerrsptr = NULL; int rv = -1; if (!metric_value_type || !metric_value_len || !metric_value) { CEREBRO_DBG(("invalid parameters")); return -1; } if (cerebro_metric_get_network(NULL, NULL, NULL, NULL, NULL, &txerrsval) < 0) goto cleanup; if (!(txerrsptr = (u_int32_t *)malloc(sizeof(u_int32_t)))) { CEREBRO_ERR(("malloc: %s", strerror(errno))); goto cleanup; } *txerrsptr = txerrsval; *metric_value_type = CEREBRO_DATA_VALUE_TYPE_U_INT32; *metric_value_len = sizeof(u_int32_t); *metric_value = (void *)txerrsptr; rv = 0; cleanup: if (rv < 0 && txerrsptr) free(txerrsptr); return rv; }
/* * genders_clusterlist_node_in_cluster * * genders clusterlist module node_in_cluster function */ static int genders_clusterlist_node_in_cluster(const char *node) { char nodebuf[CEREBRO_MAX_NODENAME_LEN+1]; char *nodePtr = NULL; int flag; if (!gh) { CEREBRO_DBG(("gh null")); return -1; } if (!node) { CEREBRO_DBG(("invalid parameters")); return -1; } /* Shorten hostname if necessary */ if (strchr(node, '.')) { char *p; memset(nodebuf, '\0', CEREBRO_MAX_NODENAME_LEN+1); strncpy(nodebuf, node, CEREBRO_MAX_NODENAME_LEN); p = strchr(nodebuf, '.'); *p = '\0'; nodePtr = nodebuf; } else nodePtr = (char *)node; if ((flag = genders_isnode(gh, nodePtr)) < 0) { CEREBRO_ERR(("genders_isnode: %s", genders_errormsg(gh))); return -1; } return flag; }
/* * _event_server_response_send * * respond to the event_server_request with an error * * Return 0 on success, -1 on error */ static int _event_server_response_send(int fd, struct cerebro_event_server_response *res) { char buf[CEREBRO_MAX_PACKET_LEN]; int res_len; assert(fd >= 0 && res); if ((res_len = _event_server_response_marshall(res, buf, CEREBRO_MAX_PACKET_LEN)) < 0) return -1; if (fd_write_n(fd, buf, res_len) < 0) { CEREBRO_ERR(("fd_write_n: %s", strerror(errno))); return -1; } return 0; }
/* * swaptotal_metric_get_metric_value * * swaptotal metric module get_metric_value function */ static int swaptotal_metric_get_metric_value(unsigned int *metric_value_type, unsigned int *metric_value_len, void **metric_value) { u_int32_t swaptotalval; u_int32_t *swaptotalptr = NULL; int rv = -1; if (!metric_value_type || !metric_value_len || !metric_value) { CEREBRO_DBG(("invalid parameters")); return -1; } if (cerebro_metric_get_memory(NULL, NULL, &swaptotalval, NULL) < 0) goto cleanup; if (!(swaptotalptr = (u_int32_t *)malloc(sizeof(u_int32_t)))) { CEREBRO_ERR(("malloc: %s", strerror(errno))); goto cleanup; } *swaptotalptr = swaptotalval; *metric_value_type = CEREBRO_DATA_VALUE_TYPE_U_INT32; *metric_value_len = sizeof(u_int32_t); *metric_value = (void *)swaptotalptr; rv = 0; cleanup: if (rv < 0 && swaptotalptr) free(swaptotalptr); return rv; }
/* * loadavg1_metric_get_metric_value * * loadavg1 metric module get_metric_value function */ static int loadavg1_metric_get_metric_value(unsigned int *metric_value_type, unsigned int *metric_value_len, void **metric_value) { float loadavg1; float *loadavgptr = NULL; int rv = -1; if (!metric_value_type || !metric_value_len || !metric_value) { CEREBRO_DBG(("invalid parameters")); return -1; } if (cerebro_metric_get_loadavgs(&loadavg1, NULL, NULL) < 0) goto cleanup; if (!(loadavgptr = (float *)malloc(sizeof(float)))) { CEREBRO_ERR(("malloc: %s", strerror(errno))); goto cleanup; } *loadavgptr = loadavg1; *metric_value_type = CEREBRO_DATA_VALUE_TYPE_FLOAT; *metric_value_len = sizeof(float); *metric_value = (void *)loadavgptr; rv = 0; cleanup: if (rv < 0 && loadavgptr) free(loadavgptr); return rv; }
/* * cerebro_metric_get_network * * Read network statistics */ int cerebro_metric_get_network(u_int64_t *bytesin, u_int64_t *bytesout, u_int32_t *packetsin, u_int32_t *packetsout, u_int32_t *rxerrs, u_int32_t *txerrs) { int len, fd = -1; char buf[NETWORK_BUFLEN]; struct timeval now; u_int64_t total_bytesin = 0; u_int64_t total_bytesout = 0; u_int32_t total_packetsin = 0; u_int32_t total_packetsout = 0; u_int32_t total_rxerrs = 0; u_int32_t total_txerrs = 0; char *parseptr; int rv = -1; if (gettimeofday(&now, NULL) < 0) { CEREBRO_ERR(("gettimeofday: %s", strerror(errno))); goto cleanup; } if ((now.tv_sec - last_read) > NETWORK_CACHETIMEOUT) { if ((fd = open(NETWORK_FILE, O_RDONLY, 0)) < 0) { CEREBRO_ERR(("open: %s", strerror(errno))); goto cleanup; } memset(buf, '\0', NETWORK_BUFLEN); if ((len = read(fd, buf, NETWORK_BUFLEN)) < 0) { CEREBRO_ERR(("read: %s", strerror(errno))); goto cleanup; } /* skip the first two lines of the file, which are headers, and * skip the local loopback interface */ parseptr = buf; if (!(parseptr = strstr(parseptr, "\n"))) { CEREBRO_ERR(("%s parse error", NETWORK_FILE)); goto cleanup; } parseptr++; if (!(parseptr = strstr(parseptr, "\n"))) { CEREBRO_ERR(("%s parse error", NETWORK_FILE)); goto cleanup; } parseptr++; if (!(parseptr = strstr(parseptr, "\n"))) { CEREBRO_ERR(("%s parse error", NETWORK_FILE)); goto cleanup; } parseptr++; while (strstr(parseptr, "\n")) { u_int64_t rx_bytes; u_int64_t tx_bytes; u_int32_t rx_packets, rx_errs; u_int32_t tx_packets, tx_errs; u_int32_t temp; char *strptr; /* skip the device name */ if (!(strptr = strstr(parseptr, ":"))) { CEREBRO_ERR(("%s parse error", NETWORK_FILE)); goto cleanup; } strptr++; rx_bytes = strtoull(strptr, &strptr, 10); if (!strptr) { CEREBRO_ERR(("%s parse error", NETWORK_FILE)); goto cleanup; } rx_packets = strtoul(strptr, &strptr, 10); if (!strptr) { CEREBRO_ERR(("%s parse error", NETWORK_FILE)); goto cleanup; } rx_errs = strtoul(strptr, &strptr, 10); if (!strptr) { CEREBRO_ERR(("%s parse error", NETWORK_FILE)); goto cleanup; } temp = strtoul(strptr, &strptr, 10); /* drop */ if (!strptr) { CEREBRO_ERR(("%s parse error", NETWORK_FILE)); goto cleanup; } temp = strtoul(strptr, &strptr, 10); /* fifo */ if (!strptr) { CEREBRO_ERR(("%s parse error", NETWORK_FILE)); goto cleanup; } temp = strtoul(strptr, &strptr, 10); /* frame */ if (!strptr) { CEREBRO_ERR(("%s parse error", NETWORK_FILE)); goto cleanup; } temp = strtoul(strptr, &strptr, 10); /* compressed */ if (!strptr) { CEREBRO_ERR(("%s parse error", NETWORK_FILE)); goto cleanup; } temp = strtoul(strptr, &strptr, 10); /* multicast */ if (!strptr) { CEREBRO_ERR(("%s parse error", NETWORK_FILE)); goto cleanup; } tx_bytes = strtoull(strptr, &strptr, 10); if (!strptr) { CEREBRO_ERR(("%s parse error", NETWORK_FILE)); goto cleanup; } tx_packets = strtoul(strptr, &strptr, 10); if (!strptr) { CEREBRO_ERR(("%s parse error", NETWORK_FILE)); goto cleanup; } tx_errs = strtoul(strptr, &strptr, 10); if (!strptr) { CEREBRO_ERR(("%s parse error", NETWORK_FILE)); goto cleanup; } total_bytesin += rx_bytes; total_packetsin += rx_packets; total_rxerrs += rx_errs; total_bytesout += tx_bytes; total_packetsout += tx_packets; total_txerrs += tx_errs; if (!(parseptr = strstr(parseptr, "\n"))) { CEREBRO_ERR(("%s parse error", NETWORK_FILE)); goto cleanup; } parseptr++; } cache_bytesin = total_bytesin; cache_bytesout = total_bytesout; cache_packetsin = total_packetsin; cache_packetsout = total_packetsout; cache_rxerrs = total_rxerrs; cache_txerrs = total_txerrs; last_read = now.tv_sec; } if (bytesin) *bytesin = cache_bytesin; if (bytesout) *bytesout = cache_bytesout; if (packetsin) *packetsin = cache_packetsin; if (packetsout) *packetsout = cache_packetsout; if (rxerrs) *rxerrs = cache_rxerrs; if (txerrs) *txerrs = cache_txerrs; rv = 0; cleanup: /* ignore potential error, just return result */ if (fd >= 0) close(fd); return rv; }
/* * _load_config_file * * Read and load configuration file * * Returns data in structure and 0 on success, -1 on error */ static int _load_config_file(struct cerebro_config *conf, unsigned int *errnum) { char *config_file = NULL; struct conffile_option options[] = { /* * Libcerebro configuration */ { "cerebro_metric_server", CONFFILE_OPTION_LIST_STRING, -1, _cb_cerebro_metric_server, CEREBRO_CONFIG_CEREBRO_METRIC_SERVERS_MAX, 0, &(conf->cerebro_metric_server_flag), conf, 0 }, { "cerebro_event_server", CONFFILE_OPTION_LIST_STRING, -1, _cb_cerebro_event_server, CEREBRO_CONFIG_CEREBRO_EVENT_SERVERS_MAX, 0, &(conf->cerebro_event_server_flag), conf, 0 }, { "cerebro_timeout_len", CONFFILE_OPTION_INT, -1, conffile_int, 1, 0, &(conf->cerebro_timeout_len_flag), &(conf->cerebro_timeout_len), 0 }, { "cerebro_flags", CONFFILE_OPTION_INT, -1, conffile_int, 1, 0, &(conf->cerebro_flags_flag), &(conf->cerebro_flags), 0 }, /* * Cerebrod configuration */ { "cerebrod_heartbeat_frequency", CONFFILE_OPTION_LIST_INT, -1, _cb_cerebrod_heartbeat_freq, 1, 0, &(conf->cerebrod_heartbeat_frequency_flag), conf, 0 }, { "cerebrod_speak", CONFFILE_OPTION_BOOL, -1, conffile_bool, 1, 0, &(conf->cerebrod_speak_flag), &conf->cerebrod_speak, 0 }, { "cerebrod_speak_message_config", CONFFILE_OPTION_LIST_STRING, -1, _cb_cerebrod_speak_message_config, CEREBRO_CONFIG_SPEAK_MESSAGE_CONFIG_MAX, 0, &(conf->cerebrod_speak_message_config_flag), conf, 0 }, { "cerebrod_speak_message_ttl", CONFFILE_OPTION_INT, -1, conffile_int, 1, 0, &(conf->cerebrod_speak_message_ttl_flag), &(conf->cerebrod_speak_message_ttl), 0 }, { "cerebrod_listen", CONFFILE_OPTION_BOOL, -1, conffile_bool, 1, 0, &(conf->cerebrod_listen_flag), &conf->cerebrod_listen, 0 }, { "cerebrod_listen_threads", CONFFILE_OPTION_INT, -1, conffile_int, 1, 0, &(conf->cerebrod_listen_threads_flag), &(conf->cerebrod_listen_threads), 0 }, { "cerebrod_listen_message_config", CONFFILE_OPTION_LIST_STRING, -1, _cb_cerebrod_listen_message_config, CEREBRO_CONFIG_LISTEN_MESSAGE_CONFIG_MAX, 0, &(conf->cerebrod_listen_message_config_flag), conf, 0 }, { "cerebrod_metric_controller", CONFFILE_OPTION_BOOL, -1, conffile_bool, 1, 0, &(conf->cerebrod_metric_controller_flag), &conf->cerebrod_metric_controller, 0 }, { "cerebrod_metric_server", CONFFILE_OPTION_BOOL, -1, conffile_bool, 1, 0, &(conf->cerebrod_metric_server_flag), &conf->cerebrod_metric_server, 0 }, { "cerebrod_metric_server_port", CONFFILE_OPTION_INT, -1, conffile_int, 1, 0, &(conf->cerebrod_metric_server_port_flag), &(conf->cerebrod_metric_server_port), 0 }, { "cerebrod_event_server", CONFFILE_OPTION_BOOL, -1, conffile_bool, 1, 0, &(conf->cerebrod_event_server_flag), &conf->cerebrod_event_server, 0 }, { "cerebrod_event_server_port", CONFFILE_OPTION_INT, -1, conffile_int, 1, 0, &(conf->cerebrod_event_server_port_flag), &(conf->cerebrod_event_server_port), 0 }, { "cerebrod_forward_message_config", CONFFILE_OPTION_LIST_STRING, -1, _cb_cerebrod_forward_message_config, CEREBRO_CONFIG_FORWARD_MESSAGE_CONFIG_MAX, 0, &(conf->cerebrod_forward_message_config_flag), conf, 0 }, { "cerebrod_forward_message_ttl", CONFFILE_OPTION_INT, -1, conffile_int, 1, 0, &(conf->cerebrod_forward_message_ttl_flag), &(conf->cerebrod_forward_message_ttl), 0 }, { "cerebrod_forward_host_accept", CONFFILE_OPTION_LIST_STRING, -1, _cb_cerebrod_forward_host_accept, CEREBRO_CONFIG_FORWARD_HOST_ACCEPT_MAX, 0, &(conf->cerebrod_forward_host_accept_flag), conf, 0 }, { "cerebrod_metric_module_exclude", CONFFILE_OPTION_LIST_STRING, -1, _cb_cerebrod_module_exclude, CEREBRO_CONFIG_METRIC_MODULE_EXCLUDE_MAX, 0, &(conf->cerebrod_metric_module_exclude_flag), conf, 0 }, { "cerebrod_monitor_module_exclude", CONFFILE_OPTION_LIST_STRING, -1, _cb_cerebrod_module_exclude, CEREBRO_CONFIG_MONITOR_MODULE_EXCLUDE_MAX, 0, &(conf->cerebrod_monitor_module_exclude_flag), conf, 0 }, { "cerebrod_event_module_exclude", CONFFILE_OPTION_LIST_STRING, -1, _cb_cerebrod_module_exclude, CEREBRO_CONFIG_EVENT_MODULE_EXCLUDE_MAX, 0, &(conf->cerebrod_event_module_exclude_flag), conf, 0 }, { "cerebrod_speak_debug", CONFFILE_OPTION_BOOL, -1, conffile_bool, 1, 0, &(conf->cerebrod_speak_debug_flag), &conf->cerebrod_speak_debug, 0 }, { "cerebrod_listen_debug", CONFFILE_OPTION_BOOL, -1, conffile_bool, 1, 0, &(conf->cerebrod_listen_debug_flag), &conf->cerebrod_listen_debug, 0 }, { "cerebrod_metric_controller_debug", CONFFILE_OPTION_BOOL, -1, conffile_bool, 1, 0, &(conf->cerebrod_metric_controller_debug_flag), &conf->cerebrod_metric_controller_debug, 0 }, { "cerebrod_metric_server_debug", CONFFILE_OPTION_BOOL, -1, conffile_bool, 1, 0, &(conf->cerebrod_metric_server_debug_flag), &conf->cerebrod_metric_server_debug, 0 }, { "cerebrod_event_server_debug", CONFFILE_OPTION_BOOL, -1, conffile_bool, 1, 0, &(conf->cerebrod_event_server_debug_flag), &conf->cerebrod_event_server_debug, 0 }, { "cerebrod_gettimeofday_workaround", CONFFILE_OPTION_BOOL, -1, conffile_bool, 1, 0, &(conf->cerebrod_gettimeofday_workaround_flag), &conf->cerebrod_gettimeofday_workaround, 0 }, #if CEREBRO_DEBUG { "cerebrod_alternate_hostname", CONFFILE_OPTION_STRING, -1, _cb_cerebrod_alternate_hostname, 1, 0, &(conf->cerebrod_alternate_hostname_flag), conf, 0 }, #endif /* CEREBRO_DEBUG */ }; conffile_t cf = NULL; int num; if (!(cf = conffile_handle_create())) { CEREBRO_ERR(("conffile_handle_create")); if (errnum) *errnum = CEREBRO_ERR_OUTMEM; goto cleanup; } if (!config_debug_config_file) config_file = CEREBRO_CONFIG_FILE_DEFAULT; else config_file = config_debug_config_file; memset(conf, '\0', sizeof(struct cerebro_config)); num = sizeof(options)/sizeof(struct conffile_option); if (conffile_parse(cf, config_file, options, num, NULL, 0, 0) < 0) { char buf[CONFFILE_MAX_ERRMSGLEN]; /* Its not an error if the default configuration file doesn't exist */ if (!strcmp(config_file, CEREBRO_CONFIG_FILE_DEFAULT) && conffile_errnum(cf) == CONFFILE_ERR_EXIST) goto out; if (conffile_errmsg(cf, buf, CONFFILE_MAX_ERRMSGLEN) < 0) CEREBRO_DBG(("conffile_parse: %d", conffile_errnum(cf))); else CEREBRO_DBG(("conffile_parse: %s", buf)); if (errnum) *errnum = CEREBRO_ERR_CONFIG_FILE; goto cleanup; } out: conffile_handle_destroy(cf); return 0; cleanup: memset(conf, '\0', sizeof(struct cerebro_config)); conffile_handle_destroy(cf); return -1; }
/* * _event_server_service_connection * * Service a connection from a client to receive event packets. Use * wrapper functions minimally, b/c we want to return errors to the * user instead of exitting with errors. * */ static void _event_server_service_connection(int fd) { int recv_len; struct cerebro_event_server_request req; struct cerebrod_event_connection_data *ecd = NULL; char buf[CEREBRO_MAX_PACKET_LEN]; char event_name_buf[CEREBRO_MAX_EVENT_NAME_LEN+1]; char *event_name_ptr = NULL; int32_t version; int *fdptr = NULL; List connections = NULL; assert(fd >= 0); memset(&req, '\0', sizeof(struct cerebro_event_server_request)); if ((recv_len = receive_data(fd, CEREBRO_EVENT_SERVER_REQUEST_PACKET_LEN, buf, CEREBRO_MAX_PACKET_LEN, CEREBRO_EVENT_SERVER_PROTOCOL_CLIENT_TIMEOUT_LEN, NULL)) < 0) goto cleanup; if (recv_len < sizeof(version)) goto cleanup; if (_event_server_request_check_version(buf, recv_len, &version) < 0) { _event_server_err_only_response(fd, version, CEREBRO_EVENT_SERVER_PROTOCOL_ERR_VERSION_INVALID); goto cleanup; } if (recv_len != CEREBRO_EVENT_SERVER_REQUEST_PACKET_LEN) { _event_server_err_only_response(fd, version, CEREBRO_EVENT_SERVER_PROTOCOL_ERR_PACKET_INVALID); goto cleanup; } if (_event_server_request_unmarshall(&req, buf, recv_len) < 0) { _event_server_err_only_response(fd, version, CEREBRO_EVENT_SERVER_PROTOCOL_ERR_PACKET_INVALID); goto cleanup; } _event_server_request_dump(&req); /* Guarantee ending '\0' character */ memset(event_name_buf, '\0', CEREBRO_MAX_EVENT_NAME_LEN+1); memcpy(event_name_buf, req.event_name, CEREBRO_MAX_EVENT_NAME_LEN); if (!strlen(event_name_buf)) { _event_server_err_only_response(fd, req.version, CEREBRO_EVENT_SERVER_PROTOCOL_ERR_EVENT_INVALID); goto cleanup; } /* Is it the special event-names request */ if (!strcmp(event_name_buf, CEREBRO_EVENT_NAMES)) { pthread_t thread; pthread_attr_t attr; int *arg; Pthread_attr_init(&attr); Pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); Pthread_attr_setstacksize(&attr, CEREBROD_THREAD_STACKSIZE); arg = Malloc(sizeof(int)); *arg = fd; Pthread_create(&thread, &attr, _respond_with_event_names, (void *)arg); Pthread_attr_destroy(&attr); return; } if (!event_names) { _event_server_err_only_response(fd, req.version, CEREBRO_EVENT_SERVER_PROTOCOL_ERR_EVENT_INVALID); goto cleanup; } /* Event names is not changeable - so no need for a lock */ if (!(event_name_ptr = list_find_first(event_names, _event_names_compare, event_name_buf))) { _event_server_err_only_response(fd, req.version, CEREBRO_EVENT_SERVER_PROTOCOL_ERR_EVENT_INVALID); goto cleanup; } if (!(ecd = (struct cerebrod_event_connection_data *)malloc(sizeof(struct cerebrod_event_connection_data)))) { CEREBRO_ERR(("malloc: %s", strerror(errno))); _event_server_err_only_response(fd, req.version, CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR); goto cleanup; } ecd->event_name = event_name_ptr; ecd->fd = fd; if (!(fdptr = (int *)malloc(sizeof(int)))) { CEREBRO_ERR(("malloc: %s", strerror(errno))); _event_server_err_only_response(fd, req.version, CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR); goto cleanup; } *fdptr = fd; Pthread_mutex_lock(&event_connections_lock); if (!list_append(event_connections, ecd)) { CEREBRO_ERR(("list_append: %s", strerror(errno))); _event_server_err_only_response(fd, req.version, CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR); goto cleanup; } if (!(connections = Hash_find(event_connections_index, ecd->event_name))) { if (!(connections = list_create((ListDelF)free))) { CEREBRO_ERR(("list_create: %s", strerror(errno))); _event_server_err_only_response(fd, req.version, CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR); goto cleanup; } if (!Hash_insert(event_connections_index, ecd->event_name, connections)) { CEREBRO_ERR(("Hash_insert: %s", strerror(errno))); _event_server_err_only_response(fd, req.version, CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR); list_destroy(connections); goto cleanup; } } if (!list_append(connections, fdptr)) { CEREBRO_ERR(("list_append: %s", strerror(errno))); _event_server_err_only_response(fd, req.version, CEREBRO_EVENT_SERVER_PROTOCOL_ERR_INTERNAL_ERROR); goto cleanup; } Pthread_mutex_unlock(&event_connections_lock); /* Clear this pointer so we know it's stored away in a list */ fdptr = NULL; _event_server_err_only_response(fd, req.version, CEREBRO_EVENT_SERVER_PROTOCOL_ERR_SUCCESS); return; cleanup: if (ecd) free(ecd); if (fdptr) free(fdptr); /* ignore potential error, we're in the error path already */ close(fd); return; }
/* * hostsfile_clusterlist_setup * * hostsfile clusterlist module setup function. Open hostsfile, read * each line of the hostsfile, and save hosts into hosts list. */ static int hostsfile_clusterlist_setup(void) { int len, fd = -1; char buf[HOSTSFILE_PARSE_BUFLEN]; char *p; if (hosts) { CEREBRO_DBG(("hosts non-null")); return 0; } if (!(hosts = list_create((ListDelF)free))) { CEREBRO_ERR(("list_create: %s", strerror(errno))); goto cleanup; } if ((fd = open(CEREBRO_CLUSTERLIST_HOSTSFILE_DEFAULT, O_RDONLY)) < 0) { CEREBRO_ERR(("hostsfile '%s' cannot be opened: %s", CEREBRO_CLUSTERLIST_HOSTSFILE_DEFAULT, strerror(errno))); goto cleanup; } while ((len = _readline(fd, buf, HOSTSFILE_PARSE_BUFLEN)) > 0) { char *hostPtr; char *str; if (!(len = _remove_comments(buf, len))) continue; if (len < 0) goto cleanup; if (!(len = _remove_trailing_whitespace(buf, len))) continue; if (len < 0) goto cleanup; if (!(hostPtr = _move_past_whitespace(buf))) goto cleanup; if (hostPtr[0] == '\0') continue; if (strchr(hostPtr, ' ') || strchr(hostPtr, '\t')) { cerebro_err_output("hostsfile host contains whitespace"); goto cleanup; } if (strlen(hostPtr) > CEREBRO_MAX_NODENAME_LEN) { cerebro_err_output("hostsfile node '%s' exceeds max length", hostPtr); goto cleanup; } /* Shorten hostname if necessary */ if ((p = strchr(hostPtr, '.'))) *p = '\0'; if (!(str = strdup(hostPtr))) { CEREBRO_ERR(("strdup: %s", strerror(errno))); goto cleanup; } if (!list_append(hosts, str)) { CEREBRO_ERR(("list_append: %s", strerror(errno))); goto cleanup; } } if (len < 0) goto cleanup; /* ignore potential error, just return result */ close(fd); return 0; cleanup: /* ignore potential error, just return result */ close(fd); if (hosts) list_destroy(hosts); hosts = NULL; return -1; }
/* * _setup_metric_modules * * Setup metric modules. Under almost any circumstance, don't return a * -1 error, cerebro can go on without loading metric modules. * * Returns 1 if modules are loaded, 0 if not, -1 on error */ static int _setup_metric_modules(void) { int i; #if CEREBRO_DEBUG #if !WITH_CEREBROD_NO_THREADS int rv; #endif /* !WITH_CEREBROD_NO_THREADS */ #endif /* CEREBRO_DEBUG */ assert(metric_list); #if CEREBRO_DEBUG #if !WITH_CEREBROD_NO_THREADS /* Should be called with lock already set */ rv = Pthread_mutex_trylock(&metric_list_lock); if (rv != EBUSY) CEREBRO_EXIT(("mutex not locked: rv=%d", rv)); #endif /* !WITH_CEREBROD_NO_THREADS */ #endif /* CEREBRO_DEBUG */ if (!(metric_handle = metric_modules_load())) { CEREBRO_DBG(("metric_modules_load")); goto cleanup; } if ((metric_handle_count = metric_modules_count(metric_handle)) < 0) { CEREBRO_DBG(("metric_module_count failed")); goto cleanup; } if (!metric_handle_count) { #if CEREBRO_DEBUG if (conf.debug && conf.speak_debug) { #if !WITH_CEREBROD_NO_THREADS Pthread_mutex_lock(&debug_output_mutex); #endif /* !WITH_CEREBROD_NO_THREADS */ fprintf(stderr, "**************************************\n"); fprintf(stderr, "* No Metric Modules Found\n"); fprintf(stderr, "**************************************\n"); #if !WITH_CEREBROD_NO_THREADS Pthread_mutex_unlock(&debug_output_mutex); #endif /* !WITH_CEREBROD_NO_THREADS */ } #endif /* CEREBRO_DEBUG */ goto cleanup; } for (i = 0; i < metric_handle_count; i++) { struct cerebrod_speaker_metric_info *metric_info; #if !WITH_CEREBROD_NO_THREADS Cerebro_metric_thread_pointer threadPtr; #endif /* !WITH_CEREBROD_NO_THREADS */ char *module_name, *metric_name; int metric_period; u_int32_t metric_flags; module_name = metric_module_name(metric_handle, i); if (conf.metric_module_exclude_len) { int found_exclude = 0; int j; for (j = 0; j < conf.metric_module_exclude_len; j++) { if (!strcasecmp(conf.metric_module_exclude[j], module_name)) { found_exclude++; break; } } if (found_exclude) { #if CEREBRO_DEBUG if (conf.debug && conf.speak_debug) { #if !WITH_CEREBROD_NO_THREADS Pthread_mutex_lock(&debug_output_mutex); #endif /* !WITH_CEREBROD_NO_THREADS */ fprintf(stderr, "**************************************\n"); fprintf(stderr, "* Skip Metric Module: %s\n", module_name); fprintf(stderr, "**************************************\n"); #if !WITH_CEREBROD_NO_THREADS Pthread_mutex_unlock(&debug_output_mutex); #endif /* !WITH_CEREBROD_NO_THREADS */ } #endif /* CEREBRO_DEBUG */ CEREBRO_ERR(("Dropping metric module: %s", module_name)); continue; } } #if CEREBRO_DEBUG if (conf.debug && conf.speak_debug) { #if !WITH_CEREBROD_NO_THREADS Pthread_mutex_lock(&debug_output_mutex); #endif /* !WITH_CEREBROD_NO_THREADS */ fprintf(stderr, "**************************************\n"); fprintf(stderr, "* Setup Metric Module: %s\n", module_name); fprintf(stderr, "**************************************\n"); #if !WITH_CEREBROD_NO_THREADS Pthread_mutex_unlock(&debug_output_mutex); #endif /* !WITH_CEREBROD_NO_THREADS */ } #endif /* CEREBRO_DEBUG */ if (metric_module_setup(metric_handle, i) < 0) { CEREBRO_DBG(("metric_module_setup: %s", module_name)); continue; } if (!(metric_name = metric_module_get_metric_name(metric_handle, i))) { CEREBRO_DBG(("metric_module_get_metric_name: %s", module_name)); metric_module_cleanup(metric_handle, i); continue; } if (metric_module_get_metric_period(metric_handle, i, &metric_period) < 0) { CEREBRO_DBG(("metric_module_get_metric_period: %s", module_name)); metric_module_cleanup(metric_handle, i); continue; } if (metric_module_get_metric_flags(metric_handle, i, &metric_flags) < 0) { CEREBRO_DBG(("metric_module_get_metric_flags: %s", module_name)); metric_module_cleanup(metric_handle, i); continue; } if (metric_flags & CEREBRO_METRIC_MODULE_FLAGS_SEND_ON_PERIOD && metric_period <= 0) { CEREBRO_DBG(("metric module period invalid: %s", module_name)); metric_module_cleanup(metric_handle, i); continue; } if (metric_module_send_message_function_pointer(metric_handle, i, &cerebrod_send_message) < 0) { CEREBRO_DBG(("metric_module_send_message_function_pointer: %s", module_name)); metric_module_cleanup(metric_handle, i); continue; } metric_info = Malloc(sizeof(struct cerebrod_speaker_metric_info)); /* No need to Strdup() the name in this case */ metric_info->metric_name = metric_name; metric_info->metric_origin = CEREBROD_METRIC_SPEAKER_ORIGIN_MODULE; metric_info->metric_period = metric_period; metric_info->metric_flags = metric_flags; metric_info->index = i; /* * If metric period is < 0, it presumably never will be sent * (metric is likely handled by a metric_thread), so set * next_call_time to UINT_MAX. * * If this is a metric that will be piggy-backed on heartbeats, * then initialize next_call_time to 0, so the data is sent on * the first heartbeat * * If this is a metric that will not be piggy-backed on * heartbeats, set the next_call_time to UINT_MAX. Let the * speaker logic decide when packets should be sent. */ if (metric_info->metric_period < 0 || metric_info->metric_flags & CEREBRO_METRIC_MODULE_FLAGS_SEND_ON_PERIOD) metric_info->next_call_time = UINT_MAX; else metric_info->next_call_time = 0; List_append(metric_list, metric_info); metric_list_size++; #if !WITH_CEREBROD_NO_THREADS if ((threadPtr = metric_module_get_metric_thread(metric_handle, i))) { pthread_t thread; pthread_attr_t attr; Pthread_attr_init(&attr); Pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); Pthread_attr_setstacksize(&attr, CEREBROD_THREAD_STACKSIZE); Pthread_create(&thread, &attr, threadPtr, NULL); Pthread_attr_destroy(&attr); } #endif /* !WITH_CEREBROD_NO_THREADS */ } if (!metric_list_size) goto cleanup; cerebrod_speaker_data_metric_list_sort(); return 1; cleanup: if (metric_handle) { /* unload will call module cleanup functions */ metric_modules_unload(metric_handle); metric_handle = NULL; metric_handle_count = 0; } metric_list_size = 0; return 0; }
/* * hostsfile_clusterlist_get_all_nodes * * hostsfile clusterlist module get_all_nodes function */ static int hostsfile_clusterlist_get_all_nodes(char ***nodes) { char **nodelist = NULL; char *node; ListIterator itr = NULL; int numnodes, i = 0; if (!hosts) { CEREBRO_DBG(("hosts null")); return -1; } if (!nodes) { CEREBRO_DBG(("invalid parameters")); return -1; } if (!(numnodes = list_count(hosts))) return 0; if (!(itr = list_iterator_create(hosts))) { CEREBRO_ERR(("list_iterator_create: %s", strerror(errno))); goto cleanup; } if (!(nodelist = (char **)malloc(sizeof(char *) * (numnodes + 1)))) { CEREBRO_ERR(("malloc: %s", strerror(errno))); goto cleanup; } memset(nodelist, '\0', sizeof(char *) * (numnodes + 1)); while ((node = list_next(itr)) && (i < numnodes)) { if (!(nodelist[i] = strdup(node))) { CEREBRO_ERR(("strdup: %s", strerror(errno))); goto cleanup; } i++; } if (i > numnodes) { CEREBRO_DBG(("iterator count error")); goto cleanup; } list_iterator_destroy(itr); *nodes = nodelist; return numnodes; cleanup: if (itr) list_iterator_destroy(itr); if (nodelist) { int j; for (j = 0; j < i; j++) free(nodelist[j]); free(nodelist); } return -1; }