static double *get_result_dbl_value(AGENT_RESULT *result) { double value; assert(result); if (0 != ISSET_DBL(result)) { /* nothing to do */ } else if (0 != ISSET_UI64(result)) { SET_DBL_RESULT(result, result->ui64); } else if (0 != ISSET_STR(result)) { zbx_rtrim(result->str, " \""); zbx_ltrim(result->str, " \"+"); if (SUCCEED != is_double(result->str)) return NULL; value = atof(result->str); SET_DBL_RESULT(result, value); } else if (0 != ISSET_TEXT(result)) { zbx_rtrim(result->text, " \""); zbx_ltrim(result->text, " \"+"); if (SUCCEED != is_double(result->text)) return NULL; value = atof(result->text); SET_DBL_RESULT(result, value); } /* skip AR_MESSAGE - it is information field */ if (0 != ISSET_DBL(result)) return &result->dbl; return NULL; }
static zbx_uint64_t *get_result_ui64_value(AGENT_RESULT *result) { zbx_uint64_t value; assert(result); if (0 != ISSET_UI64(result)) { /* nothing to do */ } else if (0 != ISSET_DBL(result)) { SET_UI64_RESULT(result, result->dbl); } else if (0 != ISSET_STR(result)) { zbx_rtrim(result->str, " \""); zbx_ltrim(result->str, " \"+"); del_zeroes(result->str); if (SUCCEED != is_uint64(result->str, &value)) return NULL; SET_UI64_RESULT(result, value); } else if (0 != ISSET_TEXT(result)) { zbx_rtrim(result->text, " \""); zbx_ltrim(result->text, " \"+"); del_zeroes(result->text); if (SUCCEED != is_uint64(result->text, &value)) return NULL; SET_UI64_RESULT(result, value); } /* skip AR_MESSAGE - it is information field */ if (0 != ISSET_UI64(result)) return &result->ui64; return NULL; }
static char *snmp_get_octet_string(struct variable_list *vars) { const char *__function_name = "snmp_get_octet_string"; static char buf[MAX_STRING_LEN]; const char *hint; char *strval_dyn = NULL, is_hex = 0; size_t offset = 0; struct tree *subtree; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); /* find the subtree to get display hint */ subtree = get_tree(vars->name, vars->name_length, get_tree_head()); hint = subtree ? subtree->hint : NULL; /* we will decide if we want the value from vars->val or what snprint_value() returned later */ if (-1 == snprint_value(buf, sizeof(buf), vars->name, vars->name_length, vars)) goto end; zabbix_log(LOG_LEVEL_DEBUG, "%s() full value:'%s'", __function_name, buf); /* decide if it's Hex, offset will be possibly needed later */ if (0 == strncmp(buf, "Hex-STRING: ", 12)) { is_hex = 1; offset = 12; } /* in case of no hex and no display hint take the value from */ /* vars->val, it contains unquoted and unescaped string */ if (0 == is_hex && NULL == hint) { strval_dyn = zbx_malloc(strval_dyn, vars->val_len + 1); memcpy(strval_dyn, vars->val.string, vars->val_len); strval_dyn[vars->val_len] = '\0'; } else { if (0 == is_hex && 0 == strncmp(buf, "STRING: ", 8)) offset = 8; strval_dyn = zbx_strdup(strval_dyn, buf + offset); } zbx_rtrim(strval_dyn, ZBX_WHITESPACE); zbx_ltrim(strval_dyn, ZBX_WHITESPACE); end: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():'%s'", __function_name, strval_dyn ? strval_dyn : "(null)"); return strval_dyn; }
/****************************************************************************** * * * Function: get_value_agent * * * * Purpose: retrieve data from Zabbix agent * * * * Parameters: item - item we are interested in * * * * Return value: SUCCEED - data successfully retrieved and stored in result * * and result_str (as string) * * NETWORK_ERROR - network related error occurred * * NOTSUPPORTED - item not supported by the agent * * AGENT_ERROR - uncritical error on agent side occurred * * FAIL - otherwise * * * * Author: Alexei Vladishev * * * * Comments: error will contain error message * * * ******************************************************************************/ int get_value_agent(DC_ITEM *item, AGENT_RESULT *result) { const char *__function_name = "get_value_agent"; zbx_socket_t s; char buffer[MAX_STRING_LEN]; int ret = SUCCEED; ssize_t received_len; zabbix_log(LOG_LEVEL_DEBUG, "In %s() host:'%s' addr:'%s' key:'%s'", __function_name, item->host.host, item->interface.addr, item->key); if (SUCCEED == (ret = zbx_tcp_connect(&s, CONFIG_SOURCE_IP, item->interface.addr, item->interface.port, 0))) { zbx_snprintf(buffer, sizeof(buffer), "%s\n", item->key); zabbix_log(LOG_LEVEL_DEBUG, "Sending [%s]", buffer); /* send requests using old protocol */ if (SUCCEED != zbx_tcp_send_raw(&s, buffer)) ret = NETWORK_ERROR; else if (FAIL != (received_len = zbx_tcp_recv_ext(&s, ZBX_TCP_READ_UNTIL_CLOSE, 0))) ret = SUCCEED; else ret = TIMEOUT_ERROR; } else ret = NETWORK_ERROR; if (SUCCEED == ret) { zbx_rtrim(s.buffer, " \r\n"); zbx_ltrim(s.buffer, " "); zabbix_log(LOG_LEVEL_DEBUG, "get value from agent result: '%s'", s.buffer); if (0 == strcmp(s.buffer, ZBX_NOTSUPPORTED)) { /* 'ZBX_NOTSUPPORTED\0<error message>' */ if (sizeof(ZBX_NOTSUPPORTED) < s.read_bytes) zbx_snprintf(buffer, sizeof(buffer), "%s", s.buffer + sizeof(ZBX_NOTSUPPORTED)); else zbx_snprintf(buffer, sizeof(buffer), "Not supported by Zabbix Agent"); SET_MSG_RESULT(result, strdup(buffer)); ret = NOTSUPPORTED; } else if (0 == strcmp(s.buffer, ZBX_ERROR)) { zbx_snprintf(buffer, sizeof(buffer), "Zabbix Agent non-critical error"); SET_MSG_RESULT(result, strdup(buffer)); ret = AGENT_ERROR; } else if (0 == received_len) { zbx_snprintf(buffer, sizeof(buffer), "Received empty response from Zabbix Agent at [%s]." " Assuming that agent dropped connection because of access permissions.", item->interface.addr); SET_MSG_RESULT(result, strdup(buffer)); ret = NETWORK_ERROR; } else if (SUCCEED != set_result_type(result, item->value_type, item->data_type, s.buffer)) ret = NOTSUPPORTED; } else { zbx_snprintf(buffer, sizeof(buffer), "Get value from agent failed: %s", zbx_socket_strerror()); SET_MSG_RESULT(result, strdup(buffer)); } zbx_tcp_close(&s); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
int set_result_type(AGENT_RESULT *result, int value_type, int data_type, char *c) { int ret = FAIL; zbx_uint64_t value_uint64; double value_double; assert(result); switch (value_type) { case ITEM_VALUE_TYPE_UINT64: zbx_rtrim(c, " \""); zbx_ltrim(c, " \"+"); del_zeroes(c); switch (data_type) { case ITEM_DATA_TYPE_BOOLEAN: if (SUCCEED == is_boolean(c, &value_uint64)) { SET_UI64_RESULT(result, value_uint64); ret = SUCCEED; } break; case ITEM_DATA_TYPE_OCTAL: if (SUCCEED == is_uoct(c)) { ZBX_OCT2UINT64(value_uint64, c); SET_UI64_RESULT(result, value_uint64); ret = SUCCEED; } break; case ITEM_DATA_TYPE_DECIMAL: if (SUCCEED == is_uint64(c, &value_uint64)) { SET_UI64_RESULT(result, value_uint64); ret = SUCCEED; } break; case ITEM_DATA_TYPE_HEXADECIMAL: if (SUCCEED == is_uhex(c)) { ZBX_HEX2UINT64(value_uint64, c); SET_UI64_RESULT(result, value_uint64); ret = SUCCEED; } else if (SUCCEED == is_hex_string(c)) { zbx_remove_whitespace(c); ZBX_HEX2UINT64(value_uint64, c); SET_UI64_RESULT(result, value_uint64); ret = SUCCEED; } break; default: THIS_SHOULD_NEVER_HAPPEN; break; } break; case ITEM_VALUE_TYPE_FLOAT: zbx_rtrim(c, " \""); zbx_ltrim(c, " \"+"); if (SUCCEED != is_double(c)) break; value_double = atof(c); SET_DBL_RESULT(result, value_double); ret = SUCCEED; break; case ITEM_VALUE_TYPE_STR: zbx_replace_invalid_utf8(c); SET_STR_RESULT(result, zbx_strdup(NULL, c)); ret = SUCCEED; break; case ITEM_VALUE_TYPE_TEXT: zbx_replace_invalid_utf8(c); SET_TEXT_RESULT(result, zbx_strdup(NULL, c)); ret = SUCCEED; break; case ITEM_VALUE_TYPE_LOG: zbx_replace_invalid_utf8(c); add_log_result(result, c); ret = SUCCEED; break; } if (SUCCEED != ret) { char *error = NULL; zbx_remove_chars(c, "\r\n"); zbx_replace_invalid_utf8(c); if (ITEM_VALUE_TYPE_UINT64 == value_type) error = zbx_dsprintf(error, "Received value [%s] is not suitable for value type [%s] and data type [%s]", c, zbx_item_value_type_string(value_type), zbx_item_data_type_string(data_type)); else error = zbx_dsprintf(error, "Received value [%s] is not suitable for value type [%s]", c, zbx_item_value_type_string(value_type)); SET_MSG_RESULT(result, error); } return ret; }
/****************************************************************************** * * * Function: parse_cfg_file * * * * Purpose: parse configuration file * * * * Parameters: cfg_file - full name of config file * * cfg - pointer to configuration parameter structure * * level - a level of included file * * optional - do not treat missing configuration file as error * * strict - treat unknown parameters as error * * * * Return value: SUCCEED - parsed successfully * * FAIL - error processing config file * * * * Author: Alexei Vladishev, Eugene Grigorjev * * * * Comments: * * * ******************************************************************************/ static int __parse_cfg_file(const char *cfg_file, struct cfg_line *cfg, int level, int optional, int strict) { #define ZBX_MAX_INCLUDE_LEVEL 10 #define ZBX_CFG_LTRIM_CHARS "\t " #define ZBX_CFG_RTRIM_CHARS ZBX_CFG_LTRIM_CHARS "\r\n" FILE *file; int i, lineno, result = SUCCEED, param_valid; char line[MAX_STRING_LEN], *parameter, *value; zbx_uint64_t var; assert(cfg); if (++level > ZBX_MAX_INCLUDE_LEVEL) { zbx_error("Recursion detected! Skipped processing of '%s'.", cfg_file); return FAIL; } if (NULL != cfg_file) { if (NULL == (file = fopen(cfg_file, "r"))) goto cannot_open; for (lineno = 1; NULL != fgets(line, sizeof(line), file); lineno++) { zbx_ltrim(line, ZBX_CFG_LTRIM_CHARS); zbx_rtrim(line, ZBX_CFG_RTRIM_CHARS); if ('#' == *line || '\0' == *line) continue; parameter = line; if (NULL == (value = strchr(line, '='))) goto garbage; *value++ = '\0'; zbx_rtrim(parameter, ZBX_CFG_RTRIM_CHARS); zbx_ltrim(value, ZBX_CFG_LTRIM_CHARS); zabbix_log(LOG_LEVEL_DEBUG, "cfg: para: [%s] val [%s]", parameter, value); if (0 == strcmp(parameter, "Include")) { if (FAIL == (result = parse_cfg_object(value, cfg, level, strict))) break; continue; } for (i = 0; '\0' != value[i]; i++) { if ('\n' == value[i]) { value[i] = '\0'; break; } } param_valid = 0; for (i = 0; NULL != cfg[i].parameter; i++) { if (0 != strcmp(cfg[i].parameter, parameter)) continue; param_valid = 1; zabbix_log(LOG_LEVEL_DEBUG, "accepted configuration parameter: '%s' = '%s'",parameter, value); if (TYPE_INT == cfg[i].type) { if (FAIL == str2uint64(value, &var)) goto incorrect_config; if ((cfg[i].min && var < cfg[i].min) || (cfg[i].max && var > cfg[i].max)) goto incorrect_config; *((int *)cfg[i].variable) = (int)var; } else if (TYPE_STRING == cfg[i].type) { /* free previous value memory */ char *p = *((char **)cfg[i].variable); if (NULL != p) zbx_free(p); *((char **)cfg[i].variable) = strdup(value); } else if (TYPE_MULTISTRING == cfg[i].type) { zbx_strarr_add(cfg[i].variable, value); } else assert(0); } if (0 == param_valid && ZBX_CFG_STRICT == strict) goto unknown_parameter; } fclose(file); } if (1 != level) /* skip mandatory parameters check for included files */ return result; for (i = 0; NULL != cfg[i].parameter; i++) /* check for mandatory parameters */ { if (PARM_MAND != cfg[i].mandatory) continue; if (TYPE_INT == cfg[i].type) { if (0 == *((int *)cfg[i].variable)) goto missing_mandatory; } else if (TYPE_STRING == cfg[i].type) { if (NULL == (*(char **)cfg[i].variable)) goto missing_mandatory; } else assert(0); } return result; cannot_open: if (optional) return result; zbx_error("cannot open config file [%s]: %s", cfg_file, zbx_strerror(errno)); exit(1); missing_mandatory: zbx_error("missing mandatory parameter [%s] in config file [%s]", cfg[i].parameter, cfg_file); exit(1); incorrect_config: fclose(file); zbx_error("wrong value of [%s] in config file [%s], line %d", cfg[i].parameter, cfg_file, lineno); exit(1); unknown_parameter: fclose(file); zbx_error("unknown parameter [%s] in config file [%s], line %d", parameter, cfg_file, lineno); exit(1); garbage: fclose(file); zbx_error("invalid entry [%s] (not following \"parameter=value\" notation) in config file [%s], line %d", line, cfg_file, lineno); exit(1); }
/****************************************************************************** * * * Function: parse_cfg_file * * * * Purpose: parse configuration file * * * * Parameters: cfg_file - full name of config file * * cfg - pointer to configuration parameter structure * * * * Return value: SUCCEED - parsed successfully * * FAIL - error processing config file * * * * Author: Alexei Vladishev, Eugene Grigorjev * * * * Comments: * * * ******************************************************************************/ static int __parse_cfg_file(const char *cfg_file, struct cfg_line *cfg, int level, int optional) { #define ZBX_MAX_INCLUDE_LEVEL 10 #define ZBX_CFG_LTRIM_CHARS "\t " #define ZBX_CFG_RTRIM_CHARS ZBX_CFG_LTRIM_CHARS "\r\n" FILE *file; int i, lineno, result = SUCCEED; char line[MAX_STRING_LEN], *parameter, *value; zbx_uint64_t var; assert(cfg); if (++level > ZBX_MAX_INCLUDE_LEVEL) { zbx_error("Recursion detected! Skipped processing of '%s'.", cfg_file); return FAIL; } if (NULL != cfg_file) { if (NULL == (file = fopen(cfg_file, "r"))) goto cannot_open; for (lineno = 1; NULL != fgets(line, sizeof(line), file); lineno++) { zbx_ltrim(line, ZBX_CFG_LTRIM_CHARS); if ('#' == *line) continue; if (strlen(line) < 3) continue; parameter = line; value = strstr(line, "="); if (NULL == value) { zbx_error("error in line [%d] \"%s\"", lineno, line); result = FAIL; break; } *value++ = '\0'; zbx_rtrim(parameter, ZBX_CFG_RTRIM_CHARS); zbx_ltrim(value, ZBX_CFG_LTRIM_CHARS); zbx_rtrim(value, ZBX_CFG_RTRIM_CHARS); zabbix_log(LOG_LEVEL_DEBUG, "cfg: para: [%s] val [%s]", parameter, value); if (0 == strcmp(parameter, "Include")) { if (FAIL == (result = parse_cfg_object(value, cfg, level))) break; } for (i = 0; '\0' != value[i]; i++) { if ('\n' == value[i]) { value[i] = '\0'; break; } } for (i = 0; NULL != cfg[i].parameter; i++) { if (0 != strcmp(cfg[i].parameter, parameter)) continue; zabbix_log(LOG_LEVEL_DEBUG, "accepted configuration parameter: '%s' = '%s'",parameter, value); if (NULL != cfg[i].function) { if (SUCCEED != cfg[i].function(value)) goto incorrect_config; } else if (TYPE_INT == cfg[i].type) { if (FAIL == str2uint64(value, &var)) goto incorrect_config; if ((cfg[i].min && var < cfg[i].min) || (cfg[i].max && var > cfg[i].max)) goto incorrect_config; *((int *)cfg[i].variable) = var; } else if (TYPE_STRING == cfg[i].type) { *((char **)cfg[i].variable) = strdup(value); } else assert(0); } } fclose(file); } if (1 != level) /* skip mandatory parameters check for included files */ return result; for (i = 0; NULL != cfg[i].parameter; i++) /* check for mandatory parameters */ { if (PARM_MAND != cfg[i].mandatory) continue; if (TYPE_INT == cfg[i].type) { if (0 == *((int *)cfg[i].variable)) goto missing_mandatory; } else if (TYPE_STRING == cfg[i].type) { if (NULL == (*(char **)cfg[i].variable)) goto missing_mandatory; } else assert(0); } return result; cannot_open: if (optional) return result; zbx_error("cannot open config file [%s] [%s]", cfg_file, strerror(errno)); exit(1); missing_mandatory: zbx_error("missing mandatory parameter [%s]", cfg[i].parameter); exit(1); incorrect_config: zbx_error("wrong value for [%s] in line %d", cfg[i].parameter, lineno); exit(1); }
int parse_cfg_file(const char *cfg_file,struct cfg_line *cfg) { FILE *file; #define ZBX_MAX_INCLUDE_LEVEL 10 #define ZBX_CFG_LTRIM_CHARS "\t " #define ZBX_CFG_RTRIM_CHARS ZBX_CFG_LTRIM_CHARS "\r\n\0" register int i, lineno; char line[MAX_STRING_LEN], *parameter, *value; int var; int result = SUCCEED; assert(cfg); // printf("%d %s\n", level, cfg_file); if(++level > ZBX_MAX_INCLUDE_LEVEL) { /* Ignore include files of depth 10 */ return result; } if(cfg_file) { if( NULL == (file = fopen(cfg_file,"r")) ) { goto lbl_cannot_open; } else { for(lineno = 1; fgets(line,MAX_STRING_LEN,file) != NULL; lineno++) { zbx_ltrim(line, ZBX_CFG_LTRIM_CHARS); if(line[0]=='#') continue; if(strlen(line) < 3) continue; parameter = line; value = strstr(line,"="); if(NULL == value) { zbx_error("Error in line [%d] \"%s\"", lineno, line); result = FAIL; break; } *value = '\0'; value++; zbx_rtrim(parameter, ZBX_CFG_RTRIM_CHARS); zbx_ltrim(value, ZBX_CFG_LTRIM_CHARS); zbx_rtrim(value, ZBX_CFG_RTRIM_CHARS); zabbix_log(LOG_LEVEL_DEBUG, "cfg: para: [%s] val [%s]", parameter, value); if(strcmp(parameter, "Include") == 0) { parse_cfg_object(value, cfg); } for(i = 0; value[i] != '\0'; i++) { if(value[i] == '\n') { value[i] = '\0'; break; } } for(i = 0; cfg[i].parameter != 0; i++) { if(strcmp(cfg[i].parameter, parameter)) continue; zabbix_log(LOG_LEVEL_DEBUG, "Accepted configuration parameter: '%s' = '%s'",parameter, value); if(cfg[i].function != 0) { if(cfg[i].function(value) != SUCCEED) goto lbl_incorrect_config; } else if(TYPE_INT == cfg[i].type) { var = atoi(value); if ( (cfg[i].min && var < cfg[i].min) || (cfg[i].max && var > cfg[i].max) ) goto lbl_incorrect_config; *((int*)cfg[i].variable) = var; } else { *((char **)cfg[i].variable) = strdup(value); } } } fclose(file); } } level--; /* Check for mandatory parameters */ if (level == 0) { // printf("here: %s\n", cfg_file); for(i = 0; cfg[i].parameter != 0; i++) { if(PARM_MAND != cfg[i].mandatory) continue; if(TYPE_INT == cfg[i].type) { if(*((int*)cfg[i].variable) == 0) goto lbl_missing_mandatory; } else if(TYPE_STRING == cfg[i].type) { if((*(char **)cfg[i].variable) == NULL) goto lbl_missing_mandatory; } } } return SUCCEED; lbl_cannot_open: zbx_error("Cannot open config file [%s] [%s].",cfg_file,strerror(errno)); exit(1); lbl_missing_mandatory: zbx_error("Missing mandatory parameter [%s].", cfg[i].parameter); exit(1); lbl_incorrect_config: zbx_error("Wrong value of [%s] in line %d.", cfg[i].parameter, lineno); exit(1); }
/****************************************************************************** * * * Function: get_value_agent * * * * Purpose: retrieve data from ZABBIX agent * * * * Parameters: item - item we are interested in * * * * Return value: SUCCEED - data successfully retrieved and stored in result * * and result_str (as string) * * NETWORK_ERROR - network related error occurred * * NOTSUPPORTED - item not supported by the agent * * AGENT_ERROR - uncritical error on agent side occurred * * FAIL - otherwise * * * * Author: Alexei Vladishev * * * * Comments: error will contain error message * * * ******************************************************************************/ int get_value_agent(DB_ITEM *item, AGENT_RESULT *result) { zbx_sock_t s; char *addr, *buf, buffer[MAX_STRING_LEN]; int ret = SUCCEED; init_result(result); addr = (item->useip == 1) ? item->host_ip : item->host_dns; zabbix_log( LOG_LEVEL_DEBUG, "In get_value_agent(host:%s,addr:%s,key:%s)", item->host_name, addr, item->key); if (SUCCEED == (ret = zbx_tcp_connect(&s, CONFIG_SOURCE_IP, addr, item->port, 0))) { zbx_snprintf(buffer, sizeof(buffer), "%s\n", item->key); zabbix_log(LOG_LEVEL_DEBUG, "Sending [%s]", buffer); /* Send requests using old protocol */ if (SUCCEED == (ret = zbx_tcp_send_raw(&s, buffer))) ret = zbx_tcp_recv_ext(&s, &buf, ZBX_TCP_READ_UNTIL_CLOSE); } if (SUCCEED == ret) { zbx_rtrim(buf, " \r\n"); zbx_ltrim(buf, " "); zabbix_log(LOG_LEVEL_DEBUG, "Get value from agent result: '%s'", buf); if (0 == strcmp(buf, "ZBX_NOTSUPPORTED")) { zbx_snprintf(buffer, sizeof(buffer), "Not supported by ZABBIX agent"); SET_MSG_RESULT(result, strdup(buffer)); ret = NOTSUPPORTED; } else if (0 == strcmp(buf, "ZBX_ERROR")) { zbx_snprintf(buffer, sizeof(buffer), "ZABBIX agent non-critical error"); SET_MSG_RESULT(result, strdup(buffer)); ret = AGENT_ERROR; } else if ('\0' == *buf) /* The section should be improved */ { zbx_snprintf(buffer, sizeof(buffer), "Got empty string from [%s]. Assuming that agent dropped connection because of access permissions", item->useip ? item->host_ip : item->host_dns); SET_MSG_RESULT(result, strdup(buffer)); ret = NETWORK_ERROR; } else if (SUCCEED != set_result_type(result, item->value_type, item->data_type, buf)) ret = NOTSUPPORTED; } else { zbx_snprintf(buffer, sizeof(buffer), "Get value from agent failed: %s", zbx_tcp_strerror()); SET_MSG_RESULT(result, strdup(buffer)); ret = NETWORK_ERROR; } zbx_tcp_close(&s); return ret; }