int PROC_NUM(AGENT_REQUEST *request, AGENT_RESULT *result) { char tmp[MAX_STRING_LEN], *procname, *proccomm, *param; DIR *dir; struct dirent *entries; zbx_stat_t buf; struct passwd *usrinfo; psinfo_t psinfo; /* In the correct procfs.h, the structure name is psinfo_t */ int fd = -1; int zbx_proc_stat; zbx_uint64_t proccount = 0; if (4 < request->nparam) return SYSINFO_RET_FAIL; procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { if (NULL == (usrinfo = getpwnam(param))) /* incorrect user name */ return SYSINFO_RET_FAIL; } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "all")) zbx_proc_stat = ZBX_PROC_STAT_ALL; else if (0 == strcmp(param, "run")) zbx_proc_stat = ZBX_PROC_STAT_RUN; else if (0 == strcmp(param, "sleep")) zbx_proc_stat = ZBX_PROC_STAT_SLEEP; else if (0 == strcmp(param, "zomb")) zbx_proc_stat = ZBX_PROC_STAT_ZOMB; else return SYSINFO_RET_FAIL; proccomm = get_rparam(request, 3); if (NULL == (dir = opendir("/proc"))) return SYSINFO_RET_FAIL; while (NULL != (entries = readdir(dir))) { if (-1 != fd) { close(fd); fd = -1; } zbx_snprintf(tmp, sizeof(tmp), "/proc/%s/psinfo", entries->d_name); if (0 != zbx_stat(tmp, &buf)) continue; if (-1 == (fd = open(tmp, O_RDONLY))) continue; if (-1 == read(fd, &psinfo, sizeof(psinfo))) continue; if (NULL != procname && '\0' != *procname && 0 != strcmp(procname, psinfo.pr_fname)) continue; if (NULL != usrinfo && usrinfo->pw_uid != psinfo.pr_uid) continue; if (FAIL == check_procstate(&psinfo, zbx_proc_stat)) continue; if (NULL != proccomm && '\0' != *proccomm && NULL == zbx_regexp_match(psinfo.pr_psargs, proccomm, NULL)) continue; proccount++; } closedir(dir); if (-1 != fd) close(fd); SET_UI64_RESULT(result, proccount); return SYSINFO_RET_OK; }
int VM_MEMORY_SIZE(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result) { PERFORMANCE_INFORMATION pfi; MEMORYSTATUSEX ms_ex; MEMORYSTATUS ms; char mode[10]; if(num_param(param) > 1) { return SYSINFO_RET_FAIL; } if(get_param(param, 1, mode, sizeof(mode)) != 0) { mode[0] = '\0'; } if(mode[0] == '\0') { /* default parameter */ zbx_snprintf(mode, sizeof(mode), "total"); } if (strcmp(mode,"cached") == 0) { if(NULL == zbx_GetPerformanceInfo) return SYSINFO_RET_FAIL; zbx_GetPerformanceInfo(&pfi,sizeof(PERFORMANCE_INFORMATION)); SET_UI64_RESULT(result, (zbx_uint64_t)pfi.SystemCache * (zbx_uint64_t)pfi.PageSize); return SYSINFO_RET_OK; } if(NULL != zbx_GlobalMemoryStatusEx) { ms_ex.dwLength = sizeof(MEMORYSTATUSEX); zbx_GlobalMemoryStatusEx(&ms_ex); if (strcmp(mode, "total") == 0) { SET_UI64_RESULT(result, ms_ex.ullTotalPhys); return SYSINFO_RET_OK; } else if (strcmp(mode, "free") == 0) { SET_UI64_RESULT(result, ms_ex.ullAvailPhys); return SYSINFO_RET_OK; } else if (strcmp(mode, "pfree") == 0) { SET_UI64_RESULT(result, (100.0 * (double)ms_ex.ullAvailPhys) / (double)ms_ex.ullTotalPhys); return SYSINFO_RET_OK; } } else { GlobalMemoryStatus(&ms); if (strcmp(mode,"total") == 0) { SET_UI64_RESULT(result, ms.dwTotalPhys); return SYSINFO_RET_OK; } else if (strcmp(mode,"free") == 0) { SET_UI64_RESULT(result, ms.dwAvailPhys); return SYSINFO_RET_OK; } else if (strcmp(mode,"pfree") == 0) { SET_UI64_RESULT(result, (100.0 * (double)ms.dwAvailPhys) / (double)ms.dwTotalPhys); return SYSINFO_RET_OK; } } return SYSINFO_RET_FAIL; }
int zbx_tcp_listen( zbx_sock_t *s, const char *listen_ip, unsigned short listen_port ) { struct addrinfo hints, *ai = NULL, *current_ai; char port[MAX_STRING_LEN]; int e, on, ret = FAIL; ZBX_TCP_START(); zbx_tcp_clean(s); memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; zbx_snprintf(port, sizeof(port), "%d", listen_port); if(0 != (e = getaddrinfo(listen_ip, port, &hints, &ai))) { zbx_set_tcp_strerror("Cannot resolve address [[%s]:%u], error %d: %s", listen_ip, listen_port, e, gai_strerror(e)); goto out; } for(s->num_socks = 0, current_ai = ai; current_ai != NULL; current_ai = current_ai->ai_next) { if(s->num_socks == FD_SETSIZE) { break; } /* This example only supports PF_INET and PF_INET6. */ if((current_ai->ai_family != PF_INET) && (current_ai->ai_family != PF_INET6)) continue; if((s->sockets[s->num_socks] = socket(current_ai->ai_family, current_ai->ai_socktype, current_ai->ai_protocol)) == ZBX_SOCK_ERROR) { zbx_set_tcp_strerror("socket() failed with error %d: %s", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error())); continue; } /* Enable address reuse */ /* This is to immediately use the address even if it is in TIME_WAIT state */ /* http://www-128.ibm.com/developerworks/linux/library/l-sockpit/index.html */ on = 1; if(setsockopt(s->sockets[s->num_socks], SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)) == ZBX_TCP_ERROR) { zbx_set_tcp_strerror("setsockopt() failed with error %d: %s", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error())); } /* Create socket Fill in local address structure */ if(bind(s->sockets[s->num_socks], current_ai->ai_addr, current_ai->ai_addrlen) == ZBX_TCP_ERROR) { zbx_set_tcp_strerror("bind() failed with error %d: %s", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error())); zbx_sock_close(s->sockets[s->num_socks]); continue; } if(ZBX_SOCK_ERROR == listen(s->sockets[s->num_socks], SOMAXCONN) ) { zbx_set_tcp_strerror("listen() failed with error %d: %s", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error())); zbx_sock_close(s->sockets[s->num_socks]); continue; } s->num_socks++; } if(s->num_socks == 0) { zbx_set_tcp_strerror("zbx_tcp_listen() Fatal error: unable to serve on any address. [[%s]:%u]", listen_ip, listen_port); goto out; } ret = SUCCEED; out: if (NULL != ai) freeaddrinfo(ai); return ret; }
/****************************************************************************** * * * Function: get_trigger_values * * * * Purpose: get trigger values for specified period * * * * Parameters: triggerid - [IN] trigger identifier from database * * maintenance_from - [IN] maintenance period start * * value_before - [OUT] trigger value before maintenance * * value_inside - [OUT] trigger value inside maintenance * * (only if value_before=value_after) * * value_after - [IN] trigger value after maintenance * * * * Return value: SUCCEED if found event with OK or PROBLEM statuses * * * ******************************************************************************/ static void get_trigger_values(zbx_uint64_t triggerid, int maintenance_from, unsigned char *value_before, unsigned char *value_inside, unsigned char value_after) { const char *__function_name = "get_trigger_values"; DB_RESULT result; DB_ROW row; char sql[256]; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); zabbix_log(LOG_LEVEL_DEBUG, "%s() from:'%s %s'", __function_name, zbx_date2str(maintenance_from), zbx_time2str(maintenance_from)); /* check for value before maintenance period */ zbx_snprintf(sql, sizeof(sql), "select value" " from events" " where source=%d" " and object=%d" " and objectid=" ZBX_FS_UI64 " and clock<%d" " order by eventid desc", EVENT_SOURCE_TRIGGERS, EVENT_OBJECT_TRIGGER, triggerid, maintenance_from); result = DBselectN(sql, 1); if (NULL != (row = DBfetch(result))) *value_before = atoi(row[0]); else *value_before = TRIGGER_VALUE_UNKNOWN; DBfree_result(result); if (value_after != *value_before) { *value_inside = TRIGGER_VALUE_UNKNOWN; /* not important what value is here */ goto out; } /* check for value inside maintenance period */ zbx_snprintf(sql, sizeof(sql), "select value" " from events" " where source=%d" " and object=%d" " and objectid=" ZBX_FS_UI64 " and clock>=%d" " and value=%d", EVENT_SOURCE_TRIGGERS, EVENT_OBJECT_TRIGGER, triggerid, maintenance_from, value_after == TRIGGER_VALUE_OK ? TRIGGER_VALUE_PROBLEM : TRIGGER_VALUE_OK); result = DBselectN(sql, 1); if (NULL != (row = DBfetch(result))) *value_inside = atoi(row[0]); else *value_inside = *value_before; DBfree_result(result); out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s() before:%d inside:%d after:%d", __function_name, (int)*value_before, (int)*value_inside, (int)value_after); }
int get_diskstat(const char *devname, zbx_uint64_t *dstat) { int i; struct devstat *ds = NULL; int ret = FAIL; char dev[DEVSTAT_NAME_LEN + 10]; const char *pd; /* pointer to device name without '/dev/' prefix, e.g. 'da0' */ assert(devname); for (i = 0; i < ZBX_DSTAT_MAX; i++) dstat[i] = (zbx_uint64_t)__UINT64_C(0); if (NULL == si) { si = (struct statinfo *)zbx_malloc(si, sizeof(struct statinfo)); si->dinfo = (struct devinfo *)zbx_malloc(NULL, sizeof(struct devinfo)); memset(si->dinfo, 0, sizeof(struct devinfo)); } pd = devname; /* skip prefix ZBX_DEV_PFX, if present */ if ('\0' != *devname && 0 == strncmp(pd, ZBX_DEV_PFX, sizeof(ZBX_DEV_PFX) - 1)) pd += sizeof(ZBX_DEV_PFX) - 1; #if DEVSTAT_USER_API_VER >= 5 if (-1 == devstat_getdevs(NULL, si)) #else if (-1 == getdevs(si)) #endif return FAIL; for (i = 0; i < si->dinfo->numdevs; i++) { ds = &si->dinfo->devices[i]; /* empty '*devname' string means adding statistics for all disks together */ if ('\0' != *devname) { zbx_snprintf(dev, sizeof(dev), "%s%d", ds->device_name, ds->unit_number); if (0 != strcmp(dev, pd)) continue; } #if DEVSTAT_USER_API_VER >= 5 dstat[ZBX_DSTAT_R_OPER] += (zbx_uint64_t)ds->operations[DEVSTAT_READ]; dstat[ZBX_DSTAT_W_OPER] += (zbx_uint64_t)ds->operations[DEVSTAT_WRITE]; dstat[ZBX_DSTAT_R_BYTE] += (zbx_uint64_t)ds->bytes[DEVSTAT_READ]; dstat[ZBX_DSTAT_W_BYTE] += (zbx_uint64_t)ds->bytes[DEVSTAT_WRITE]; #else dstat[ZBX_DSTAT_R_OPER] += (zbx_uint64_t)ds->num_reads; dstat[ZBX_DSTAT_W_OPER] += (zbx_uint64_t)ds->num_writes; dstat[ZBX_DSTAT_R_BYTE] += (zbx_uint64_t)ds->bytes_read; dstat[ZBX_DSTAT_W_BYTE] += (zbx_uint64_t)ds->bytes_written; #endif ret = SUCCEED; if ('\0' != *devname) break; } return ret; }
int zbx_tcp_listen(zbx_sock_t *s, const char *listen_ip, unsigned short listen_port) { struct addrinfo hints, *ai = NULL, *current_ai; char port[8], *ip, *ips, *delim; int i, err, on, ret = FAIL; ZBX_TCP_START(); zbx_tcp_clean(s); memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; zbx_snprintf(port, sizeof(port), "%hu", listen_port); ip = ips = (NULL == listen_ip ? NULL : strdup(listen_ip)); while (1) { delim = (NULL == ip ? NULL : strchr(ip, ',')); if (NULL != delim) *delim = '\0'; if (0 != (err = getaddrinfo(ip, port, &hints, &ai))) { zbx_set_tcp_strerror("cannot resolve address [[%s]:%s]: [%d] %s", ip ? ip : "-", port, err, gai_strerror(err)); goto out; } for (current_ai = ai; NULL != current_ai; current_ai = current_ai->ai_next) { if (ZBX_SOCKET_COUNT == s->num_socks) { zbx_set_tcp_strerror("not enough space for socket [[%s]:%s]", ip ? ip : "-", port); goto out; } if (PF_INET != current_ai->ai_family && PF_INET6 != current_ai->ai_family) continue; if (ZBX_SOCK_ERROR == (s->sockets[s->num_socks] = socket(current_ai->ai_family, current_ai->ai_socktype | SOCK_CLOEXEC, current_ai->ai_protocol))) { zbx_set_tcp_strerror("socket() for [[%s]:%s] failed: %s", ip ? ip : "-", port, strerror_from_system(zbx_sock_last_error())); #ifdef _WINDOWS if (WSAEAFNOSUPPORT == zbx_sock_last_error()) #else if (EAFNOSUPPORT == zbx_sock_last_error()) #endif continue; else goto out; } #if !defined(_WINDOWS) && !SOCK_CLOEXEC fcntl(s->sockets[s->num_socks], F_SETFD, FD_CLOEXEC); #endif /* enable address reuse */ /* this is to immediately use the address even if it is in TIME_WAIT state */ /* http://www-128.ibm.com/developerworks/linux/library/l-sockpit/index.html */ on = 1; if (ZBX_TCP_ERROR == setsockopt(s->sockets[s->num_socks], SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on))) { zbx_set_tcp_strerror("setsockopt() with SO_REUSEADDR for [[%s]:%s] failed: %s", ip ? ip : "-", port, strerror_from_system(zbx_sock_last_error())); } #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) if (PF_INET6 == current_ai->ai_family && ZBX_TCP_ERROR == setsockopt(s->sockets[s->num_socks], IPPROTO_IPV6, IPV6_V6ONLY, (void *)&on, sizeof(on))) { zbx_set_tcp_strerror("setsockopt() with IPV6_V6ONLY for [[%s]:%s] failed: %s", ip ? ip : "-", port, strerror_from_system(zbx_sock_last_error())); } #endif if (ZBX_TCP_ERROR == bind(s->sockets[s->num_socks], current_ai->ai_addr, current_ai->ai_addrlen)) { zbx_set_tcp_strerror("bind() for [[%s]:%s] failed: %s", ip ? ip : "-", port, strerror_from_system(zbx_sock_last_error())); zbx_sock_close(s->sockets[s->num_socks]); #ifdef _WINDOWS if (WSAEADDRINUSE == zbx_sock_last_error()) #else if (EADDRINUSE == zbx_sock_last_error()) #endif continue; else goto out; } if (ZBX_TCP_ERROR == listen(s->sockets[s->num_socks], SOMAXCONN)) { zbx_set_tcp_strerror("listen() for [[%s]:%s] failed: %s", ip ? ip : "-", port, strerror_from_system(zbx_sock_last_error())); zbx_sock_close(s->sockets[s->num_socks]); goto out; } s->num_socks++; } if (NULL != ai) { freeaddrinfo(ai); ai = NULL; } if (NULL == ip || NULL == delim) break; *delim = ','; ip = delim + 1; } if (0 == s->num_socks) { zbx_set_tcp_strerror("zbx_tcp_listen() fatal error: unable to serve on any address [[%s]:%hu]", listen_ip, listen_port); goto out; } ret = SUCCEED; out: if (NULL != ips) zbx_free(ips); if (NULL != ai) freeaddrinfo(ai); if (SUCCEED != ret) { for (i = 0; i < s->num_socks; i++) zbx_sock_close(s->sockets[i]); } return ret; }
int SYSTEM_HW_MACADDR(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result) { size_t offset; int ret = SYSINFO_RET_FAIL, s, i, show_names; char *p, regex[MAX_STRING_LEN], address[MAX_STRING_LEN], buffer[MAX_STRING_LEN]; struct ifreq *ifr; struct ifconf ifc; zbx_vector_str_t addresses; if (2 < num_param(param)) return ret; if (0 != get_param(param, 1, regex, sizeof(regex)) || 0 == strcmp(regex, "all")) *regex = '\0'; if (0 != get_param(param, 2, buffer, sizeof(buffer)) || '\0' == *buffer || 0 == strcmp(buffer, "full")) show_names = 1; /* show interface names */ else if (0 == strcmp(buffer, "short")) show_names = 0; else return ret; if (-1 == (s = socket(AF_INET, SOCK_DGRAM, 0))) return ret; /* get the interface list */ ifc.ifc_len = sizeof(buffer); ifc.ifc_buf = buffer; if (-1 == ioctl(s, SIOCGIFCONF, &ifc)) goto close; ifr = ifc.ifc_req; ret = SYSINFO_RET_OK; zbx_vector_str_create(&addresses); zbx_vector_str_reserve(&addresses, 8); /* go through the list */ for (i = ifc.ifc_len / sizeof(struct ifreq); 0 < i--; ifr++) { if ('\0' != *regex && NULL == zbx_regexp_match(ifr->ifr_name, regex, NULL)) continue; if (-1 != ioctl(s, SIOCGIFFLAGS, ifr) && /* get the interface */ 0 == (ifr->ifr_flags & IFF_LOOPBACK) && /* skip loopback interface */ -1 != ioctl(s, SIOCGIFHWADDR, ifr)) /* get the MAC address */ { offset = 0; if (1 == show_names) offset += zbx_snprintf(address + offset, sizeof(address) - offset, "[%s ", ifr->ifr_name); zbx_snprintf(address + offset, sizeof(address) - offset, "%.2hx:%.2hx:%.2hx:%.2hx:%.2hx:%.2hx", (unsigned short int)(unsigned char)ifr->ifr_hwaddr.sa_data[0], (unsigned short int)(unsigned char)ifr->ifr_hwaddr.sa_data[1], (unsigned short int)(unsigned char)ifr->ifr_hwaddr.sa_data[2], (unsigned short int)(unsigned char)ifr->ifr_hwaddr.sa_data[3], (unsigned short int)(unsigned char)ifr->ifr_hwaddr.sa_data[4], (unsigned short int)(unsigned char)ifr->ifr_hwaddr.sa_data[5]); if (0 == show_names && FAIL != zbx_vector_str_search(&addresses, address, ZBX_DEFAULT_STR_COMPARE_FUNC)) continue; zbx_vector_str_append(&addresses, zbx_strdup(NULL, address)); } } offset = 0; if (0 != addresses.values_num) { zbx_vector_str_sort(&addresses, ZBX_DEFAULT_STR_COMPARE_FUNC); for (i = 0; i < addresses.values_num; i++) { if (1 == show_names && NULL != (p = strchr(addresses.values[i], ' '))) *p = ']'; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%s, ", addresses.values[i]); zbx_free(addresses.values[i]); } offset -= 2; } buffer[offset] = '\0'; if (SYSINFO_RET_OK == ret) SET_STR_RESULT(result, zbx_strdup(NULL, buffer)); zbx_vector_str_destroy(&addresses); close: close(s); return ret; }
/****************************************************************************** * * * 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; }
void load_oids(void) { char sql[1024]; char *hostname; char *community; char *oid; MYSQL_RES *result; int i; struct host *h; struct oid *o; zbx_snprintf(sql, sizeof(sql), "select h.ip,i.snmp_community,i.snmp_oid from hosts h,items i where i.hostid=h.hostid and i.type=1 and i.status=0 and h.status=0 and h.useip=1"); result=DBselect(sql); for(i=0;i<DBnum_rows(result);i++) { /* printf("[%s] [%s] [%s]\n",DBget_field(result,i,0),DBget_field(result,i,1),DBget_field(result,i,2)); */ hostname = DBget_field(result,i,0); community = DBget_field(result,i,1); oid = DBget_field(result,i,2); h = hosts; while(h->hostname) { if(strcmp(h->hostname,hostname)==0) break; h++; } if(!h->hostname) { h->hostname=strdup(hostname); h->community=strdup(community); h++; h->hostname = NULL; } o = oids; while(o->hostname) { o++; } o->hostname=strdup(hostname); o->Name=strdup(oid); o++; o->hostname = NULL; } h = hosts; i = 0; while(h->hostname) { i++; h++; } printf("Loaded [%d] hosts\n", i); o = oids; i = 0; while(o->hostname) { i++; o++; } printf("Loaded [%d] OIDs\n", i); }
/****************************************************************************** * * * Function: zbx_execute_script * * * * Purpose: executing user scripts or remote commands * * * * Parameters: * * * * Return value: SUCCEED - processed successfully * * FAIL - an error occurred * * * * Author: Alexander Vladishev * * * * Comments: !!! always call 'zbx_script_clean' function after * * 'zbx_execute_script' to clear allocated memory * * * ******************************************************************************/ int zbx_execute_script(DC_HOST *host, zbx_script_t *script, char **result, char *error, size_t max_error_len) { const char *__function_name = "zbx_execute_script"; int ret = FAIL; zbx_uint64_t groupid; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); *error = '\0'; switch (script->type) { case ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT: dos2unix(script->command); /* CR+LF (Windows) => LF (Unix) */ switch (script->execute_on) { case ZBX_SCRIPT_EXECUTE_ON_AGENT: ret = zbx_execute_script_on_agent(host, script->command, result, error, max_error_len); break; case ZBX_SCRIPT_EXECUTE_ON_SERVER: ret = zbx_execute(script->command, result, error, max_error_len, CONFIG_TRAPPER_TIMEOUT); break; default: zbx_snprintf(error, max_error_len, "Invalid 'Execute on' option [%d]", (int)script->execute_on); } break; case ZBX_SCRIPT_TYPE_IPMI: #ifdef HAVE_OPENIPMI if (SUCCEED == (ret = zbx_execute_ipmi_command(host, script->command, error, max_error_len))) { if (NULL != result) *result = zbx_strdup(*result, "IPMI command successfully executed"); } #else zbx_strlcpy(error, "Support for IPMI commands was not compiled in", max_error_len); #endif break; case ZBX_SCRIPT_TYPE_SSH: #ifdef HAVE_SSH2 substitute_simple_macros(NULL, &host->hostid, NULL, NULL, NULL, &script->publickey, MACRO_TYPE_ITEM_FIELD, NULL, 0); substitute_simple_macros(NULL, &host->hostid, NULL, NULL, NULL, &script->privatekey, MACRO_TYPE_ITEM_FIELD, NULL, 0); #else zbx_strlcpy(error, "Support for SSH script was not compiled in", max_error_len); break; #endif case ZBX_SCRIPT_TYPE_TELNET: substitute_simple_macros(NULL, &host->hostid, NULL, NULL, NULL, &script->username, MACRO_TYPE_ITEM_FIELD, NULL, 0); substitute_simple_macros(NULL, &host->hostid, NULL, NULL, NULL, &script->password, MACRO_TYPE_ITEM_FIELD, NULL, 0); ret = zbx_execute_script_on_terminal(host, script, result, error, max_error_len); break; case ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT: if (SUCCEED != DBget_script_by_scriptid(script->scriptid, script, &groupid)) { zbx_snprintf(error, max_error_len, "Unknown Script ID [" ZBX_FS_UI64 "]", script->scriptid); break; } if (SUCCEED == check_script_permissions(groupid, host->hostid, error, max_error_len)) { substitute_simple_macros(NULL, NULL, host, NULL, NULL, &script->command, MACRO_TYPE_SCRIPT, NULL, 0); ret = zbx_execute_script(host, script, result, error, max_error_len); /* recursion */ } break; default: zbx_snprintf(error, max_error_len, "Invalid command type [%d]", (int)script->type); } if (FAIL == ret && NULL != result) *result = zbx_strdup(*result, ""); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
int RUN_COMMAND(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result) { #define MAX_FLAG_LEN 10 char command[MAX_STRING_LEN]; char flag[MAX_FLAG_LEN]; #if defined (_WINDOWS) STARTUPINFO si; PROCESS_INFORMATION pi; char full_command[MAX_STRING_LEN]; #else /* not _WINDOWS */ pid_t pid; #endif assert(result); init_result(result); if (CONFIG_ENABLE_REMOTE_COMMANDS != 1) { SET_MSG_RESULT(result, strdup("ZBX_NOTSUPPORTED")); return SYSINFO_RET_FAIL; } if (num_param(param) > 2) return SYSINFO_RET_FAIL; if (0 != get_param(param, 1, command, sizeof(command))) return SYSINFO_RET_FAIL; if (*command == '\0') return SYSINFO_RET_FAIL; zabbix_log(LOG_LEVEL_DEBUG, "Run command '%s'", command); if (0 != get_param(param, 2, flag, sizeof(flag))) *flag = '\0'; if (*flag == '\0') zbx_snprintf(flag, sizeof(flag), "wait"); if (0 == strcmp(flag, "wait")) return EXECUTE_STR(cmd,command,flags,result); else if(0 != strcmp(flag,"nowait")) return SYSINFO_RET_FAIL; #if defined(_WINDOWS) zbx_snprintf(full_command, sizeof(full_command), "cmd /C \"%s\"", command); GetStartupInfo(&si); zabbix_log(LOG_LEVEL_DEBUG, "Execute command '%s'",full_command); if(!CreateProcess( NULL, /* No module name (use command line) */ full_command,/* Name of app to launch */ NULL, /* Default process security attributes */ NULL, /* Default thread security attributes */ FALSE, /* Don't inherit handles from the parent */ 0, /* Normal priority */ NULL, /* Use the same environment as the parent */ NULL, /* Launch in the current directory */ &si, /* Startup Information */ &pi)) /* Process information stored upon return */ { return SYSINFO_RET_FAIL; } #else /* not _WINDOWS */ pid = zbx_fork(); /* run new thread 1 */ switch(pid) { case -1: zabbix_log(LOG_LEVEL_WARNING, "fork failed for command '%s'",command); return SYSINFO_RET_FAIL; case 0: pid = zbx_fork(); /* run new tread 2 to replace by command */ switch(pid) { case -1: zabbix_log(LOG_LEVEL_WARNING, "fork2 failed for '%s'",command); return SYSINFO_RET_FAIL; case 0: /* * DON'T REMOVE SLEEP * sleep needed to return server result as "1" * then we can run "execl" * otherwise command print result into socket with STDOUT id */ sleep(3); /**/ /* replace thread 2 by the execution of command */ if(execl("/bin/sh", "sh", "-c", command, (char *)0)) { zabbix_log(LOG_LEVEL_WARNING, "execl failed for command '%s'",command); } /* In normal case the program will never reach this point */ exit(0); default: waitpid(pid, NULL, WNOHANG); /* NO WAIT can be used for thread 2 closing */ exit(0); /* close thread 1 and transmit thread 2 to system (solve zombie state) */ break; } default: waitpid(pid, NULL, 0); /* wait thread 1 closing */ break; } #endif /* _WINDOWS */ SET_UI64_RESULT(result, 1); return SYSINFO_RET_OK; }
static int zbx_execute_script_on_terminal(DC_HOST *host, zbx_script_t *script, char **result, char *error, size_t max_error_len) { const char *__function_name = "zbx_execute_script_on_terminal"; int ret; AGENT_RESULT agent_result; DC_ITEM item; int (*function)(); #ifdef HAVE_SSH2 assert(ZBX_SCRIPT_TYPE_SSH == script->type || ZBX_SCRIPT_TYPE_TELNET == script->type); #else assert(ZBX_SCRIPT_TYPE_TELNET == script->type); #endif zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); *error = '\0'; memset(&item, 0, sizeof(item)); memcpy(&item.host, host, sizeof(item.host)); if (SUCCEED != (ret = DCconfig_get_interface_by_type(&item.interface, host->hostid, INTERFACE_TYPE_AGENT))) { zbx_snprintf(error, max_error_len, "Zabbix agent interface is not defined for host [%s]", host->host); goto fail; } item.username = script->username; item.publickey = script->publickey; item.privatekey = script->privatekey; item.password = script->password; substitute_simple_macros(NULL, &host->hostid, NULL, NULL, NULL, &script->port, MACRO_TYPE_INTERFACE_PORT, NULL, 0); if ('\0' != *script->port && SUCCEED != (ret = is_ushort(script->port, NULL))) { zbx_snprintf(error, max_error_len, "Invalid port number [%s]", script->port); goto fail; } #ifdef HAVE_SSH2 if (ZBX_SCRIPT_TYPE_SSH == script->type) { item.key = zbx_dsprintf(item.key, "ssh.run[,,%s]", script->port); function = get_value_ssh; } else { #endif item.key = zbx_dsprintf(item.key, "telnet.run[,,%s]", script->port); function = get_value_telnet; #ifdef HAVE_SSH2 } #endif item.value_type = ITEM_VALUE_TYPE_TEXT; item.params = zbx_strdup(item.params, script->command); init_result(&agent_result); alarm(CONFIG_TIMEOUT); if (SUCCEED != (ret = function(&item, &agent_result))) { if (ISSET_MSG(&agent_result)) zbx_strlcpy(error, agent_result.msg, max_error_len); ret = FAIL; } else if (NULL != result && ISSET_TEXT(&agent_result)) *result = zbx_strdup(*result, agent_result.text); alarm(0); free_result(&agent_result); zbx_free(item.params); zbx_free(item.key); fail: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
int SYSTEM_CPU_LOAD(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result) { char cpuname[10], mode[10]; if(num_param(param) > 2) { return SYSINFO_RET_FAIL; } if(get_param(param, 1, cpuname, sizeof(cpuname)) != 0) { cpuname[0] = '\0'; } if(cpuname[0] == '\0') { /* default parameter */ zbx_snprintf(cpuname, sizeof(cpuname), "all"); } if(get_param(param, 2, mode, sizeof(mode)) != 0) { mode[0] = '\0'; } if(mode[0] == '\0') { /* default parameter */ zbx_snprintf(mode, sizeof(mode), "avg1"); } if(strcmp(cpuname,"all") != 0) { return SYSINFO_RET_FAIL; } if ( !CPU_COLLECTOR_STARTED(collector) ) { SET_MSG_RESULT(result, strdup("Collector is not started!")); return SYSINFO_RET_OK; } if(strcmp(mode,"avg1") == 0) { SET_DBL_RESULT(result, collector->cpus.load1); } else if(strcmp(mode,"avg5") == 0) { SET_DBL_RESULT(result, collector->cpus.load5); } else if(strcmp(mode,"avg15") == 0) { SET_DBL_RESULT(result, collector->cpus.load15); } else { return SYSINFO_RET_FAIL; } return SYSINFO_RET_OK; }
int PROC_MEM(AGENT_REQUEST *request, AGENT_RESULT *result) { char tmp[MAX_STRING_LEN], *procname, *proccomm, *param; DIR *dir; struct dirent *entries; zbx_stat_t buf; struct passwd *usrinfo; psinfo_t psinfo; /* In the correct procfs.h, the structure name is psinfo_t */ int fd = -1; zbx_uint64_t value = 0; int do_task; double memsize = 0; zbx_uint64_t proccount = 0; if (4 < request->nparam) return SYSINFO_RET_FAIL; procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { if (NULL == (usrinfo = getpwnam(param))) /* incorrect user name */ return SYSINFO_RET_FAIL; } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "sum")) do_task = DO_SUM; else if (0 == strcmp(param, "avg")) do_task = DO_AVG; else if (0 == strcmp(param, "max")) do_task = DO_MAX; else if (0 == strcmp(param, "min")) do_task = DO_MIN; else return SYSINFO_RET_FAIL; proccomm = get_rparam(request, 3); if (NULL == (dir = opendir("/proc"))) return SYSINFO_RET_FAIL; while (NULL != (entries = readdir(dir))) { if (-1 != fd) { close(fd); fd = -1; } zbx_snprintf(tmp, sizeof(tmp), "/proc/%s/psinfo", entries->d_name); if (0 != zbx_stat(tmp, &buf)) continue; if (-1 == (fd = open(tmp, O_RDONLY))) continue; if (-1 == read(fd, &psinfo, sizeof(psinfo))) continue; if (NULL != procname && '\0' != *procname && 0 != strcmp(procname, psinfo.pr_fname)) continue; if (NULL != usrinfo && usrinfo->pw_uid != psinfo.pr_uid) continue; if (NULL != proccomm && '\0' != *proccomm && NULL == zbx_regexp_match(psinfo.pr_psargs, proccomm, NULL)) continue; value = psinfo.pr_size; value <<= 10; /* kB to Byte */ if (0 == proccount++) memsize = value; else { if (do_task == DO_MAX) memsize = MAX(memsize, value); else if (do_task == DO_MIN) memsize = MIN(memsize, value); else memsize += value; } } closedir(dir); if (-1 != fd) close(fd); if (do_task == DO_AVG) { SET_DBL_RESULT(result, proccount == 0 ? 0 : memsize / proccount); } else { SET_UI64_RESULT(result, memsize); } return SYSINFO_RET_OK; }
/****************************************************************************** * * * Function: proc_read_cpu_util * * * * Purpose: reads process cpu utilization values from /proc/[pid]/stat file * * * * Parameters: procutil - [IN/OUT] the process cpu utilization data * * * * Return value: SUCCEED - the process cpu utilization data was read * * successfully * * <0 - otherwise, -errno code is returned * * * ******************************************************************************/ static int proc_read_cpu_util(zbx_procstat_util_t *procutil) { int n, offset, fd, ret = SUCCEED; char tmp[MAX_STRING_LEN], *ptr; zbx_snprintf(tmp, sizeof(tmp), "/proc/%d/stat", (int)procutil->pid); if (-1 == (fd = open(tmp, O_RDONLY))) return -errno; if (-1 == (n = read(fd, tmp, sizeof(tmp) - 1))) { ret = -errno; goto out; } tmp[n] = '\0'; /* skip to the end of process name to avoid dealing with possible spaces in process name */ if (NULL == (ptr = strrchr(tmp, ')'))) { ret = -EFAULT; goto out; } n = 0; while ('\0' != *ptr) { if (' ' != *ptr++) continue; switch (++n) { case 12: if (FAIL == (offset = proc_read_value(ptr, &procutil->utime))) { ret = -EINVAL; goto out; } ptr += offset; break; case 13: if (FAIL == (offset = proc_read_value(ptr, &procutil->stime))) { ret = -EINVAL; goto out; } ptr += offset; break; case 20: if (FAIL == (offset = proc_read_value(ptr, &procutil->starttime))) { ret = -EINVAL; goto out; } goto out; } } ret = -ENODATA; out: close(fd); return ret; }
static zbx_ipmi_host_t *init_ipmi_host(const char *ip, int port, int authtype, int privilege, const char *username, const char *password) { const char *__function_name = "init_ipmi_host"; zbx_ipmi_host_t *h; ipmi_open_option_t options[4]; struct timeval tv; char *addrs[1] = {NULL}, *ports[1] = {NULL}, domain_name[11]; /* max int length */ int ret; zabbix_log(LOG_LEVEL_DEBUG, "In %s() host:'[%s]:%d'", __function_name, ip, port); h = get_ipmi_host(ip, port, authtype, privilege, username, password); if (NULL != h) { if (1 == h->domain_up) goto out; } else h = allocate_ipmi_host(ip, port, authtype, privilege, username, password); h->ret = SUCCEED; h->done = 0; addrs[0] = strdup(h->ip); ports[0] = zbx_dsprintf(NULL, "%d", h->port); if (0 != (ret = ipmi_ip_setup_con(addrs, ports, 1, h->authtype == -1 ? (unsigned int)IPMI_AUTHTYPE_DEFAULT : (unsigned int)h->authtype, (unsigned int)h->privilege, h->username, strlen(h->username), h->password, strlen(h->password), os_hnd, NULL, &h->con))) { h->err = zbx_dsprintf(h->err, "Cannot connect to IPMI host [%s]:%d." " ipmi_ip_setup_con() returned error 0x%x", h->ip, h->port, ret); h->ret = NETWORK_ERROR; goto out; } if (0 != (ret = h->con->start_con(h->con))) { h->err = zbx_dsprintf(h->err, "Cannot connect to IPMI host [%s]:%d." " start_con() returned error 0x%x", h->ip, h->port, ret); h->ret = NETWORK_ERROR; goto out; } options[0].option = IPMI_OPEN_OPTION_ALL; options[0].ival = 0; options[1].option = IPMI_OPEN_OPTION_SDRS; /* scan SDRs */ options[1].ival = 1; options[2].option = IPMI_OPEN_OPTION_IPMB_SCAN; /* scan IPMB bus to find out as much as possible */ options[2].ival = 1; options[3].option = IPMI_OPEN_OPTION_LOCAL_ONLY; /* scan only local resources */ options[3].ival = 1; zbx_snprintf(domain_name, sizeof(domain_name), "%d", h->domain_id); if (0 != (ret = ipmi_open_domain(domain_name, &h->con, 1, setup_done, h, domain_up, h, options, ARRSIZE(options), NULL))) { h->err = zbx_dsprintf(h->err, "Cannot connect to IPMI host [%s]:%d. ipmi_open_domain() failed: %s", h->ip, h->port, zbx_strerror(ret)); h->ret = NETWORK_ERROR; goto out; } tv.tv_sec = 10; tv.tv_usec = 0; while (0 == h->done) os_hnd->perform_one_op(os_hnd, &tv); out: zbx_free(addrs[0]); zbx_free(ports[0]); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%p domain_id:%u", __function_name, h, h->domain_id); return h; }
int zbx_tcp_connect(zbx_sock_t *s, const char *source_ip, const char *ip, unsigned short port, int timeout) { int ret = FAIL; struct addrinfo *ai = NULL, hints; struct addrinfo *ai_bind = NULL; char service[8]; ZBX_TCP_START(); zbx_tcp_clean(s); zbx_snprintf(service, sizeof(service), "%d", port); memset(&hints, 0x00, sizeof(struct addrinfo)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if (0 != getaddrinfo(ip, service, &hints, &ai)) { zbx_set_tcp_strerror("cannot resolve [%s]", ip); goto out; } if (ZBX_SOCK_ERROR == (s->socket = socket(ai->ai_family, ai->ai_socktype | SOCK_CLOEXEC, ai->ai_protocol))) { zbx_set_tcp_strerror("cannot create socket [[%s]:%d]: %s", ip, port, strerror_from_system(zbx_sock_last_error())); goto out; } #if !defined(_WINDOWS) && !SOCK_CLOEXEC fcntl(s->socket, F_SETFD, FD_CLOEXEC); #endif if (NULL != source_ip) { memset(&hints, 0x00, sizeof(struct addrinfo)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICHOST; if (0 != getaddrinfo(source_ip, NULL, &hints, &ai_bind)) { zbx_set_tcp_strerror("invalid source IP address [%s]", source_ip); goto out; } if (ZBX_TCP_ERROR == bind(s->socket, ai_bind->ai_addr, ai_bind->ai_addrlen)) { zbx_set_tcp_strerror("bind() failed: %s", strerror_from_system(zbx_sock_last_error())); goto out; } } if (0 != timeout) zbx_tcp_timeout_set(s, timeout); if (ZBX_TCP_ERROR == connect(s->socket, ai->ai_addr, ai->ai_addrlen)) { zbx_set_tcp_strerror("*** Cannot connect to [[%s]:%d]: %s", ip, port, strerror_from_system(zbx_sock_last_error())); zbx_tcp_close(s); goto out; } ret = SUCCEED; out: if (NULL != ai) freeaddrinfo(ai); if (NULL != ai_bind) freeaddrinfo(ai_bind); return ret; }
/****************************************************************************** * * * Function: send_list_of_active_checks * * * * Purpose: send list of active checks to the host (older version agent) * * * * Parameters: sock - open socket of server-agent connection * * request - request buffer * * * * Return value: SUCCEED - list of active checks sent successfully * * FAIL - an error occurred * * * * Comments: format of the request: ZBX_GET_ACTIVE_CHECKS\n<host name>\n * * format of the list: key:delay:last_log_size * * * ******************************************************************************/ int send_list_of_active_checks(zbx_sock_t *sock, char *request) { const char *__function_name = "send_list_of_active_checks"; char *host = NULL, *p, *buffer = NULL, error[MAX_STRING_LEN], ip[INTERFACE_IP_LEN_MAX]; size_t buffer_alloc = 8 * ZBX_KIBIBYTE, buffer_offset = 0; int ret = FAIL, i; zbx_uint64_t hostid; zbx_vector_uint64_t itemids; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (NULL != (host = strchr(request, '\n'))) { host++; if (NULL != (p = strchr(host, '\n'))) *p = '\0'; } else { zbx_snprintf(error, sizeof(error), "host is null"); goto out; } strscpy(ip, get_ip_by_socket(sock)); /* no host metadata in older versions of agent */ if (FAIL == get_hostid_by_host(host, ip, ZBX_DEFAULT_AGENT_PORT, "", &hostid, error)) goto out; zbx_vector_uint64_create(&itemids); get_list_of_active_checks(hostid, &itemids); buffer = zbx_malloc(buffer, buffer_alloc); if (0 != itemids.values_num) { DC_ITEM *dc_items; int *errcodes, refresh_unsupported, now; dc_items = zbx_malloc(NULL, sizeof(DC_ITEM) * itemids.values_num); errcodes = zbx_malloc(NULL, sizeof(int) * itemids.values_num); DCconfig_get_items_by_itemids(dc_items, itemids.values, errcodes, itemids.values_num); DCconfig_get_config_data(&refresh_unsupported, CONFIG_REFRESH_UNSUPPORTED); now = time(NULL); for (i = 0; i < itemids.values_num; i++) { if (SUCCEED != errcodes[i]) { zabbix_log(LOG_LEVEL_DEBUG, "%s() Item [" ZBX_FS_UI64 "] was not found in the" " server cache. Not sending now.", __function_name, itemids.values[i]); continue; } if (ITEM_STATUS_ACTIVE != dc_items[i].status) continue; if (HOST_STATUS_MONITORED != dc_items[i].host.status) continue; if (ITEM_STATE_NOTSUPPORTED == dc_items[i].state) { if (0 == refresh_unsupported || dc_items[i].lastclock + refresh_unsupported > now) continue; } zbx_snprintf_alloc(&buffer, &buffer_alloc, &buffer_offset, "%s:%d:" ZBX_FS_UI64 "\n", dc_items[i].key_orig, dc_items[i].delay, dc_items[i].lastlogsize); } DCconfig_clean_items(dc_items, errcodes, itemids.values_num); zbx_free(errcodes); zbx_free(dc_items); } zbx_vector_uint64_destroy(&itemids); zbx_strcpy_alloc(&buffer, &buffer_alloc, &buffer_offset, "ZBX_EOF\n"); zabbix_log(LOG_LEVEL_DEBUG, "%s() sending [%s]", __function_name, buffer); alarm(CONFIG_TIMEOUT); if (SUCCEED != zbx_tcp_send_raw(sock, buffer)) zbx_strlcpy(error, zbx_tcp_strerror(), MAX_STRING_LEN); else ret = SUCCEED; alarm(0); zbx_free(buffer); out: if (FAIL == ret) { zabbix_log(LOG_LEVEL_WARNING, "cannot send list of active checks to [%s]: %s", get_ip_by_socket(sock), error); } zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
int SYSTEM_HW_CPU(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result) { int ret = SYSINFO_RET_FAIL, filter, cpu, cur_cpu = -1, offset = 0; zbx_uint64_t maxfreq = FAIL, curfreq = FAIL; char line[MAX_STRING_LEN], name[MAX_STRING_LEN], tmp[MAX_STRING_LEN], buffer[MAX_BUFFER_LEN]; FILE *f; if (2 < num_param(param)) return ret; if (0 != get_param(param, 1, tmp, sizeof(tmp)) || '\0' == *tmp || 0 == strcmp(tmp, "all")) cpu = HW_CPU_ALL_CPUS; /* show all CPUs by default */ else if (FAIL == is_uint(tmp)) return ret; else cpu = atoi(tmp); if (0 != get_param(param, 2, tmp, sizeof(tmp)) || '\0' == *tmp || 0 == strcmp(tmp, "full")) filter = HW_CPU_SHOW_ALL; /* show full info by default */ else if (0 == strcmp(tmp, "maxfreq")) filter = HW_CPU_SHOW_MAXFREQ; else if (0 == strcmp(tmp, "vendor")) filter = HW_CPU_SHOW_VENDOR; else if (0 == strcmp(tmp, "model")) filter = HW_CPU_SHOW_MODEL; else if (0 == strcmp(tmp, "curfreq")) filter = HW_CPU_SHOW_CURFREQ; else return ret; if (NULL == (f = fopen(HW_CPU_INFO_FILE, "r"))) return ret; *buffer = '\0'; while (NULL != fgets(line, sizeof(line), f)) { if (2 != sscanf(line, "%[^:]: %[^\n]", name, tmp)) continue; if (0 == strncmp(name, "processor", 9)) { if (-1 != cur_cpu && (HW_CPU_ALL_CPUS == cpu || cpu == cur_cpu)) /* print info about the previous cpu */ offset += print_freq(buffer + offset, sizeof(buffer) - offset, filter, cpu, maxfreq, curfreq); curfreq = FAIL; cur_cpu = atoi(tmp); if (HW_CPU_ALL_CPUS != cpu && cpu != cur_cpu) continue; if (HW_CPU_ALL_CPUS == cpu || HW_CPU_SHOW_ALL == filter) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\nprocessor %d:", cur_cpu); if ((HW_CPU_SHOW_ALL == filter || HW_CPU_SHOW_MAXFREQ == filter) && FAIL != (maxfreq = get_cpu_max_freq(cur_cpu))) { ret = SYSINFO_RET_OK; } } if (HW_CPU_ALL_CPUS != cpu && cpu != cur_cpu) continue; if (0 == strncmp(name, "vendor_id", 9) && (HW_CPU_SHOW_ALL == filter || HW_CPU_SHOW_VENDOR == filter)) { ret = SYSINFO_RET_OK; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", tmp); } else if (0 == strncmp(name, "model name", 10) && (HW_CPU_SHOW_ALL == filter || HW_CPU_SHOW_MODEL == filter)) { ret = SYSINFO_RET_OK; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", tmp); } else if (0 == strncmp(name, "cpu MHz", 7) && (HW_CPU_SHOW_ALL == filter || HW_CPU_SHOW_CURFREQ == filter)) { ret = SYSINFO_RET_OK; ZBX_STR2UINT64(curfreq, tmp); } } zbx_fclose(f); if (SYSINFO_RET_OK == ret) { if (-1 != cur_cpu && (HW_CPU_ALL_CPUS == cpu || cpu == cur_cpu)) /* print info about the last cpu */ offset += print_freq(buffer + offset, sizeof(buffer) - offset, filter, cpu, maxfreq, curfreq); SET_TEXT_RESULT(result, zbx_strdup(NULL, buffer + 1)); /* buf has a leading space or '\n' */ } return ret; }
/****************************************************************************** * * * Function: send_list_of_active_checks_json * * * * Purpose: send list of active checks to the host * * * * Parameters: sock - open socket of server-agent connection * * json - request buffer * * * * Return value: SUCCEED - list of active checks sent successfully * * FAIL - an error occurred * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ int send_list_of_active_checks_json(zbx_sock_t *sock, struct zbx_json_parse *jp) { const char *__function_name = "send_list_of_active_checks_json"; #define ZBX_KEY_OTHER 0 #define ZBX_KEY_LOG 1 #define ZBX_KEY_EVENTLOG 2 char host[HOST_HOST_LEN_MAX], params[MAX_STRING_LEN], tmp[MAX_STRING_LEN], ip[INTERFACE_IP_LEN_MAX], error[MAX_STRING_LEN], *host_metadata = NULL; struct zbx_json json; int ret = FAIL, i; zbx_uint64_t hostid; size_t host_metadata_alloc = 1; /* for at least NUL-termination char */ unsigned short port; zbx_vector_uint64_t itemids; unsigned char item_key; zbx_vector_ptr_t regexps; zbx_vector_str_t names; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); zbx_vector_ptr_create(®exps); zbx_vector_str_create(&names); if (FAIL == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_HOST, host, sizeof(host))) { zbx_snprintf(error, MAX_STRING_LEN, "%s", zbx_json_strerror()); goto error; } host_metadata = zbx_malloc(host_metadata, host_metadata_alloc); if (FAIL == zbx_json_value_by_name_dyn(jp, ZBX_PROTO_TAG_HOST_METADATA, &host_metadata, &host_metadata_alloc)) { *host_metadata = '\0'; } if (FAIL == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_IP, ip, sizeof(ip))) strscpy(ip, get_ip_by_socket(sock)); if (FAIL == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_PORT, tmp, sizeof(tmp))) *tmp = '\0'; if (FAIL == is_ushort(tmp, &port)) port = ZBX_DEFAULT_AGENT_PORT; if (FAIL == get_hostid_by_host(host, ip, port, host_metadata, &hostid, error)) goto error; zbx_vector_uint64_create(&itemids); get_list_of_active_checks(hostid, &itemids); zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN); zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS, ZBX_JSON_TYPE_STRING); zbx_json_addarray(&json, ZBX_PROTO_TAG_DATA); if (0 != itemids.values_num) { DC_ITEM *dc_items; int *errcodes, refresh_unsupported, now; dc_items = zbx_malloc(NULL, sizeof(DC_ITEM) * itemids.values_num); errcodes = zbx_malloc(NULL, sizeof(int) * itemids.values_num); DCconfig_get_items_by_itemids(dc_items, itemids.values, errcodes, itemids.values_num); DCconfig_get_config_data(&refresh_unsupported, CONFIG_REFRESH_UNSUPPORTED); now = time(NULL); for (i = 0; i < itemids.values_num; i++) { if (SUCCEED != errcodes[i]) { zabbix_log(LOG_LEVEL_DEBUG, "%s() Item [" ZBX_FS_UI64 "] was not found in the" " server cache. Not sending now.", __function_name, itemids.values[i]); continue; } if (ITEM_STATUS_ACTIVE != dc_items[i].status) continue; if (HOST_STATUS_MONITORED != dc_items[i].host.status) continue; if (ITEM_STATE_NOTSUPPORTED == dc_items[i].state) { if (0 == refresh_unsupported || dc_items[i].lastclock + refresh_unsupported > now) continue; } dc_items[i].key = zbx_strdup(dc_items[i].key, dc_items[i].key_orig); substitute_key_macros(&dc_items[i].key, NULL, &dc_items[i], NULL, MACRO_TYPE_ITEM_KEY, NULL, 0); zbx_json_addobject(&json, NULL); zbx_json_addstring(&json, ZBX_PROTO_TAG_KEY, dc_items[i].key, ZBX_JSON_TYPE_STRING); if (0 != strcmp(dc_items[i].key, dc_items[i].key_orig)) { zbx_json_addstring(&json, ZBX_PROTO_TAG_KEY_ORIG, dc_items[i].key_orig, ZBX_JSON_TYPE_STRING); } zbx_json_adduint64(&json, ZBX_PROTO_TAG_DELAY, dc_items[i].delay); /* The agent expects ALWAYS to have lastlogsize and mtime tags. */ /* Removing those would cause older agents to fail. */ zbx_json_adduint64(&json, ZBX_PROTO_TAG_LOGLASTSIZE, dc_items[i].lastlogsize); zbx_json_adduint64(&json, ZBX_PROTO_TAG_MTIME, dc_items[i].mtime); zbx_json_close(&json); if (0 == strncmp(dc_items[i].key, "log[", 4) || 0 == strncmp(dc_items[i].key, "logrt[", 6)) item_key = ZBX_KEY_LOG; else if (0 == strncmp(dc_items[i].key, "eventlog[", 9)) item_key = ZBX_KEY_EVENTLOG; else item_key = ZBX_KEY_OTHER; if (ZBX_KEY_OTHER != item_key && ZBX_COMMAND_WITH_PARAMS == parse_command(dc_items[i].key, NULL, 0, params, sizeof(params))) { /* "params" parameter */ if (0 == get_param(params, 2, tmp, sizeof(tmp)) && '@' == *tmp) zbx_vector_str_append_uniq(&names, tmp + 1); if (ZBX_KEY_EVENTLOG == item_key) { /* "severity" parameter */ if (0 == get_param(params, 3, tmp, sizeof(tmp)) && '@' == *tmp) zbx_vector_str_append_uniq(&names, tmp + 1); /* "source" parameter */ if (0 == get_param(params, 4, tmp, sizeof(tmp)) && '@' == *tmp) zbx_vector_str_append_uniq(&names, tmp + 1); /* "logeventid" parameter */ if (0 == get_param(params, 5, tmp, sizeof(tmp)) && '@' == *tmp) zbx_vector_str_append_uniq(&names, tmp + 1); } } zbx_free(dc_items[i].key); } DCconfig_clean_items(dc_items, errcodes, itemids.values_num); zbx_free(errcodes); zbx_free(dc_items); } zbx_vector_uint64_destroy(&itemids); zbx_json_close(&json); DCget_expressions_by_names(®exps, (const char * const *)names.values, names.values_num); if (0 < regexps.values_num) { char buffer[32]; zbx_json_addarray(&json, ZBX_PROTO_TAG_REGEXP); for (i = 0; i < regexps.values_num; i++) { zbx_expression_t *regexp = regexps.values[i]; zbx_json_addobject(&json, NULL); zbx_json_addstring(&json, "name", regexp->name, ZBX_JSON_TYPE_STRING); zbx_json_addstring(&json, "expression", regexp->expression, ZBX_JSON_TYPE_STRING); zbx_snprintf(buffer, sizeof(buffer), "%d", regexp->expression_type); zbx_json_addstring(&json, "expression_type", buffer, ZBX_JSON_TYPE_INT); zbx_snprintf(buffer, sizeof(buffer), "%c", regexp->exp_delimiter); zbx_json_addstring(&json, "exp_delimiter", buffer, ZBX_JSON_TYPE_STRING); zbx_snprintf(buffer, sizeof(buffer), "%d", regexp->case_sensitive); zbx_json_addstring(&json, "case_sensitive", buffer, ZBX_JSON_TYPE_INT); zbx_json_close(&json); } zbx_json_close(&json); } zabbix_log(LOG_LEVEL_DEBUG, "%s() sending [%s]", __function_name, json.buffer); alarm(CONFIG_TIMEOUT); if (SUCCEED != zbx_tcp_send(sock, json.buffer)) strscpy(error, zbx_tcp_strerror()); else ret = SUCCEED; alarm(0); zbx_json_free(&json); goto out; error: zabbix_log(LOG_LEVEL_WARNING, "cannot send list of active checks to [%s]: %s", get_ip_by_socket(sock), error); zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN); zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_FAILED, ZBX_JSON_TYPE_STRING); zbx_json_addstring(&json, ZBX_PROTO_TAG_INFO, error, ZBX_JSON_TYPE_STRING); zabbix_log(LOG_LEVEL_DEBUG, "%s() sending [%s]", __function_name, json.buffer); ret = zbx_tcp_send(sock, json.buffer); zbx_json_free(&json); out: for (i = 0; i < names.values_num; i++) zbx_free(names.values[i]); zbx_vector_str_destroy(&names); zbx_regexp_clean_expressions(®exps); zbx_vector_ptr_destroy(®exps); zbx_free(host_metadata); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
/* * Custom key pg.backends.count * * Returns statistics for connected backends (remote clients) * * Parameters: * 0: connection string * 1: connection database * 2: filter by database oid name * 3: filter by user OID or name * 4: filter by hostname or IP address of the connected host * 5: return only waiting backends * * Returns: u */ int PG_BACKENDS_COUNT(AGENT_REQUEST *request, AGENT_RESULT *result) { int ret = SYSINFO_RET_FAIL; // Request result code const char *__function_name = "PG_BACKENDS_COUNT"; // Function name for log file char query[MAX_QUERY_LEN]; char *p = &query[0]; int i = 0; char *param = NULL; char *clause = PG_WHERE; PGparams pgparams = NULL; int pgi = 0; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); // Build the sql query memset(query, 0, MAX_QUERY_LEN); zbx_strlcpy(p, PGSQL_GET_BACKENDS, MAX_QUERY_LEN); p += strlen(p); // iterate over the available parameters for(i = 0; i < 4; i++) { param = get_rparam(request, PARAM_FIRST + i); if(!strisnull(param)) { switch(i) { case 0: // <database> pgparams = param_append(pgparams, param); if(is_oid(param)) zbx_snprintf(p, MAX_CLAUSE_LEN, " %s datid=$%i", clause, ++pgi); else zbx_snprintf(p, MAX_CLAUSE_LEN, " %s datname=$%i", clause, ++pgi); break; case 1: // <user> pgparams = param_append(pgparams, param); if(is_oid(param)) zbx_snprintf(p, MAX_CLAUSE_LEN, " %s usesysid=$%i", clause, ++pgi); else zbx_snprintf(p, MAX_CLAUSE_LEN, " %s usename=$%i", clause, ++pgi); break; case 2: // <client> pgparams = param_append(pgparams, param); if(is_valid_ip(param)) zbx_snprintf(p, MAX_CLAUSE_LEN, " %s client_addr = $%i::inet", clause, ++pgi); else // requires v9.1+ zbx_snprintf(p, MAX_CLAUSE_LEN, " %s client_hostname=$%i", clause, ++pgi); break; case 3: // <waiting> if(0 == strncmp("true", param, 4)) { zbx_snprintf(p, MAX_CLAUSE_LEN, " %s waiting=TRUE", clause); } else if(0 == strncmp("false", param, 5)) { zbx_snprintf(p, MAX_CLAUSE_LEN, " %s waiting=FALSE", clause); } else { zabbix_log(LOG_LEVEL_ERR, "Unsupported 'Waiting' parameter: %s in %s()", param, __function_name); goto out; } break; } p += strlen(p); clause = PG_AND; } } ret = pg_get_int(request, result, query, pgparams); out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); return ret; }
/****************************************************************************** * * * Function: get_hostid_by_host * * * * Purpose: check for host name and return hostid * * * * Parameters: host - [IN] require size 'HOST_HOST_LEN_MAX' * * * * Return value: SUCCEED - host is found * * FAIL - an error occurred or host not found * * * * Author: Alexander Vladishev * * * * Comments: NB! adds host to the database if it does not exist * * * ******************************************************************************/ static int get_hostid_by_host(const char *host, const char *ip, unsigned short port, const char *host_metadata, zbx_uint64_t *hostid, char *error) { const char *__function_name = "get_hostid_by_host"; char *host_esc, dns[INTERFACE_DNS_LEN_MAX], *ch_error; DB_RESULT result; DB_ROW row; int ret = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s() host:'%s'", __function_name, host); if (FAIL == zbx_check_hostname(host, &ch_error)) { zbx_snprintf(error, MAX_STRING_LEN, "invalid host name [%s]: %s", host, ch_error); zbx_free(ch_error); goto out; } host_esc = DBdyn_escape_string(host); result = DBselect( "select hostid,status" " from hosts" " where host='%s'" " and status in (%d,%d)" " and flags<>%d" " and proxy_hostid is null", host_esc, HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED, ZBX_FLAG_DISCOVERY_PROTOTYPE); if (NULL != (row = DBfetch(result))) { if (HOST_STATUS_MONITORED == atoi(row[1])) { ZBX_STR2UINT64(*hostid, row[0]); ret = SUCCEED; } else zbx_snprintf(error, MAX_STRING_LEN, "host [%s] not monitored", host); } else { zbx_snprintf(error, MAX_STRING_LEN, "host [%s] not found", host); /* remove ::ffff: prefix from IPv4-mapped IPv6 addresses */ if (0 == strncmp("::ffff:", ip, 7) && SUCCEED == is_ip4(ip + 7)) ip += 7; alarm(CONFIG_TIMEOUT); zbx_gethost_by_ip(ip, dns, sizeof(dns)); alarm(0); DBbegin(); if (0 != (daemon_type & ZBX_DAEMON_TYPE_SERVER)) DBregister_host(0, host, ip, dns, port, host_metadata, (int)time(NULL)); else if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY)) DBproxy_register_host(host, ip, dns, port, host_metadata); DBcommit(); } DBfree_result(result); zbx_free(host_esc); out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
/****************************************************************************** * * * Function: get_proxyconfig_table * * * * Purpose: prepare proxy configuration data * * * * Parameters: * * * * Return value: SUCCEED - processed successfully * * FAIL - an error occurred * * * * Author: Aleksander Vladishev * * * * Comments: * * * ******************************************************************************/ static int get_proxyconfig_table(zbx_uint64_t proxy_hostid, struct zbx_json *j, ZBX_TABLE *table, const char *reltable, const char *relfield) { char sql[MAX_STRING_LEN]; int offset = 0, f, fld; DB_RESULT result; DB_ROW row; zabbix_log(LOG_LEVEL_DEBUG, "In get_proxyconfig_table() [proxy_hostid:" ZBX_FS_UI64 "] [table:%s]", proxy_hostid, table->table); zbx_json_addobject(j, table->table); zbx_json_addarray(j, "fields"); offset += zbx_snprintf(sql + offset, sizeof(sql) - offset, "select t.%s", table->recid); zbx_json_addstring(j, NULL, table->recid, ZBX_JSON_TYPE_STRING); for (f = 0; table->fields[f].name != 0; f ++) { if ((table->fields[f].flags & ZBX_PROXY) == 0) continue; offset += zbx_snprintf(sql + offset, sizeof(sql) - offset, ",t.%s", table->fields[f].name); zbx_json_addstring(j, NULL, table->fields[f].name, ZBX_JSON_TYPE_STRING); } zbx_json_close(j); offset += zbx_snprintf(sql + offset, sizeof(sql) - offset, " from %s t", table->table); if (NULL == reltable) offset += zbx_snprintf(sql + offset, sizeof(sql) - offset, " where t.proxy_hostid=" ZBX_FS_UI64, proxy_hostid); else offset += zbx_snprintf(sql + offset, sizeof(sql) - offset, ", %s r where t.%s=r.%s" " and r.proxy_hostid=" ZBX_FS_UI64, reltable, relfield, relfield, proxy_hostid); if (0 == strcmp(table->table, "hosts")) offset += zbx_snprintf(sql + offset, sizeof(sql) - offset, " and t.status=%d", HOST_STATUS_MONITORED); if (NULL != reltable && 0 == strcmp(reltable, "hosts")) offset += zbx_snprintf(sql + offset, sizeof(sql) - offset, " and r.status=%d", HOST_STATUS_MONITORED); if (0 == strcmp(table->table, "items")) offset += zbx_snprintf(sql + offset, sizeof(sql) - offset, " and t.status in (%d,%d)", ITEM_STATUS_ACTIVE, ITEM_STATUS_NOTSUPPORTED); if (0 == strcmp(table->table, "drules")) offset += zbx_snprintf(sql + offset, sizeof(sql) - offset, " and t.status=%d", DRULE_STATUS_MONITORED); if (NULL != reltable && 0 == strcmp(reltable, "drules")) offset += zbx_snprintf(sql + offset, sizeof(sql) - offset, " and r.status=%d", DRULE_STATUS_MONITORED); offset += zbx_snprintf(sql + offset, sizeof(sql) - offset, " order by t.%s", table->recid); zbx_json_addarray(j, "data"); result = DBselect("%s", sql); while (NULL != (row = DBfetch(result))) { fld = 0; zbx_json_addarray(j, NULL); zbx_json_addstring(j, NULL, row[fld++], ZBX_JSON_TYPE_INT); for (f = 0; table->fields[f].name != 0; f ++) { if ((table->fields[f].flags & ZBX_PROXY) == 0) continue; switch (table->fields[f].type) { case ZBX_TYPE_INT: case ZBX_TYPE_UINT: case ZBX_TYPE_ID: zbx_json_addstring(j, NULL, row[fld++], ZBX_JSON_TYPE_INT); break; default: zbx_json_addstring(j, NULL, row[fld++], ZBX_JSON_TYPE_STRING); break; } } zbx_json_close(j); } DBfree_result(result); zbx_json_close(j); zbx_json_close(j); return SUCCEED; }
int PROC_INFO(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result) { DWORD *procList, dwSize; HMODULE *modList; HANDLE hProcess; char proc_name[MAX_PATH], attr[MAX_PATH], type[MAX_PATH], baseName[MAX_PATH]; const char *attrList[] = {"vmsize", "wkset", "pf", "ktime", "utime", "gdiobj", "userobj", "io_read_b", "io_read_op", "io_write_b", "io_write_op", "io_other_b", "io_other_op", NULL}, *typeList[] = {"min", "max", "avg", "sum", NULL}; double value; int i, proc_cnt, counter, attr_id, type_id, ret = SYSINFO_RET_OK; if (num_param(param) > 3) return SYSINFO_RET_FAIL; if (0 != get_param(param, 1, proc_name, sizeof(proc_name))) *proc_name = '\0'; if ('\0' == *proc_name) return SYSINFO_RET_FAIL; if (0 != get_param(param, 2, attr, sizeof(attr))) *attr = '\0'; if ('\0' == *attr) /* default parameter */ zbx_snprintf(attr, sizeof(attr), "%s", attrList[0]); if (0 != get_param(param, 3, type, sizeof(type))) *type = '\0'; if ('\0' == *type) /* default parameter */ zbx_snprintf(type, sizeof(type), "%s", typeList[2]); /* Get attribute code from string */ for (attr_id = 0; NULL != attrList[attr_id] && 0 != strcmp(attrList[attr_id], attr); attr_id++) ; if (NULL == attrList[attr_id]) /* Unsupported attribute */ return SYSINFO_RET_FAIL; /* Get type code from string */ for (type_id = 0; NULL != typeList[type_id] && 0 != strcmp(typeList[type_id], type); type_id++) ; if (NULL == typeList[type_id]) return SYSINFO_RET_FAIL; /* Unsupported type */ procList = (DWORD *)malloc(MAX_PROCESSES * sizeof(DWORD)); modList = (HMODULE *)malloc(MAX_MODULES * sizeof(HMODULE)); EnumProcesses(procList, sizeof(DWORD) * MAX_PROCESSES, &dwSize); proc_cnt = dwSize / sizeof(DWORD); counter = 0; value = 0; for (i = 0; i < proc_cnt; i++) { if (NULL != (hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE, procList[i]))) { if (0 != EnumProcessModules(hProcess, modList, sizeof(HMODULE) * MAX_MODULES, &dwSize)) if (0 != GetModuleBaseName(hProcess,modList[0],baseName,sizeof(baseName))) if (0 == stricmp(baseName, proc_name)) if (SYSINFO_RET_OK != (ret = GetProcessAttribute(hProcess, attr_id, type_id, ++counter, &value))) break; CloseHandle(hProcess); } } free(procList); free(modList); if (SYSINFO_RET_OK == ret) SET_DBL_RESULT(result, value) return ret; }
/****************************************************************************** * * * Function: discover_service * * * * Purpose: check if service is available and update database * * * * Parameters: service type, ip address, port number * * * * Author: Alexei Vladishev * * * ******************************************************************************/ static int discover_service(DB_DCHECK *dcheck, char *ip, int port, char *value) { const char *__function_name = "discover_service"; int ret = SUCCEED; char key[MAX_STRING_LEN], error[ITEM_ERROR_LEN_MAX]; const char *service = NULL; AGENT_RESULT result; DC_ITEM item; ZBX_FPING_HOST host; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); init_result(&result); *value = '\0'; switch (dcheck->type) { case SVC_SSH: service = "ssh"; break; case SVC_LDAP: service = "ldap"; break; case SVC_SMTP: service = "smtp"; break; case SVC_FTP: service = "ftp"; break; case SVC_HTTP: service = "http"; break; case SVC_POP: service = "pop"; break; case SVC_NNTP: service = "nntp"; break; case SVC_IMAP: service = "imap"; break; case SVC_TCP: service = "tcp"; break; case SVC_HTTPS: service = "https"; break; case SVC_TELNET: service = "telnet"; break; case SVC_AGENT: case SVC_SNMPv1: case SVC_SNMPv2c: case SVC_SNMPv3: case SVC_ICMPPING: break; default: ret = FAIL; break; } if (SUCCEED == ret) { alarm(CONFIG_TIMEOUT); switch (dcheck->type) { /* simple checks */ case SVC_SSH: case SVC_LDAP: case SVC_SMTP: case SVC_FTP: case SVC_HTTP: case SVC_POP: case SVC_NNTP: case SVC_IMAP: case SVC_TCP: case SVC_HTTPS: case SVC_TELNET: zbx_snprintf(key, sizeof(key), "net.tcp.service[%s,%s,%d]", service, ip, port); if (SUCCEED != process(key, 0, &result) || NULL == GET_UI64_RESULT(&result) || 0 == result.ui64) { ret = FAIL; } break; /* agent and SNMP checks */ case SVC_AGENT: case SVC_SNMPv1: case SVC_SNMPv2c: case SVC_SNMPv3: memset(&item, 0, sizeof(DC_ITEM)); strscpy(item.key_orig, dcheck->key_); item.key = item.key_orig; item.interface.useip = 1; item.interface.addr = ip; item.interface.port = port; item.value_type = ITEM_VALUE_TYPE_STR; switch (dcheck->type) { case SVC_SNMPv1: item.type = ITEM_TYPE_SNMPv1; break; case SVC_SNMPv2c: item.type = ITEM_TYPE_SNMPv2c; break; case SVC_SNMPv3: item.type = ITEM_TYPE_SNMPv3; break; default: item.type = ITEM_TYPE_ZABBIX; break; } if (SVC_AGENT == dcheck->type) { if (SUCCEED == get_value_agent(&item, &result) && NULL != GET_STR_RESULT(&result)) zbx_strlcpy(value, result.str, DSERVICE_VALUE_LEN_MAX); else ret = FAIL; } else #ifdef HAVE_SNMP { item.snmp_community = strdup(dcheck->snmp_community); item.snmp_oid = strdup(dcheck->key_); substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, NULL, &item.snmp_community, MACRO_TYPE_COMMON, NULL, 0); substitute_key_macros(&item.snmp_oid, NULL, NULL, NULL, MACRO_TYPE_SNMP_OID, NULL, 0); if (ITEM_TYPE_SNMPv3 == item.type) { item.snmpv3_securityname = zbx_strdup(NULL, dcheck->snmpv3_securityname); item.snmpv3_securitylevel = dcheck->snmpv3_securitylevel; item.snmpv3_authpassphrase = zbx_strdup(NULL, dcheck->snmpv3_authpassphrase); item.snmpv3_privpassphrase = zbx_strdup(NULL, dcheck->snmpv3_privpassphrase); item.snmpv3_authprotocol = dcheck->snmpv3_authprotocol; item.snmpv3_privprotocol = dcheck->snmpv3_privprotocol; item.snmpv3_contextname = zbx_strdup(NULL, dcheck->snmpv3_contextname); substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, NULL, &item.snmpv3_securityname, MACRO_TYPE_COMMON, NULL, 0); substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, NULL, &item.snmpv3_authpassphrase, MACRO_TYPE_COMMON, NULL, 0); substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, NULL, &item.snmpv3_privpassphrase, MACRO_TYPE_COMMON, NULL, 0); substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, NULL, &item.snmpv3_contextname, MACRO_TYPE_COMMON, NULL, 0); } if (SUCCEED == get_value_snmp(&item, &result) && NULL != GET_STR_RESULT(&result)) zbx_strlcpy(value, result.str, DSERVICE_VALUE_LEN_MAX); else ret = FAIL; zbx_free(item.snmp_community); zbx_free(item.snmp_oid); if (ITEM_TYPE_SNMPv3 == item.type) { zbx_free(item.snmpv3_securityname); zbx_free(item.snmpv3_authpassphrase); zbx_free(item.snmpv3_privpassphrase); zbx_free(item.snmpv3_contextname); } } #else ret = FAIL; #endif /* HAVE_SNMP */ if (FAIL == ret && ISSET_MSG(&result)) { zabbix_log(LOG_LEVEL_DEBUG, "discovery: item [%s] error: %s", item.key, result.msg); } break; case SVC_ICMPPING: memset(&host, 0, sizeof(host)); host.addr = strdup(ip); if (SUCCEED != do_ping(&host, 1, 3, 0, 0, 0, error, sizeof(error)) || 0 == host.rcv) ret = FAIL; zbx_free(host.addr); break; default: break; } alarm(0); } free_result(&result); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
int PROC_MEM(AGENT_REQUEST *request, AGENT_RESULT *result) { #define ZBX_SIZE 0 #define ZBX_RSS 1 #define ZBX_VSIZE 2 #define ZBX_PMEM 3 #define ZBX_VMPEAK 4 #define ZBX_VMSWAP 5 #define ZBX_VMLIB 6 #define ZBX_VMLCK 7 #define ZBX_VMPIN 8 #define ZBX_VMHWM 9 #define ZBX_VMDATA 10 #define ZBX_VMSTK 11 #define ZBX_VMEXE 12 #define ZBX_VMPTE 13 char tmp[MAX_STRING_LEN], *procname, *proccomm, *param; DIR *dir; struct dirent *entries; struct passwd *usrinfo; FILE *f_cmd = NULL, *f_stat = NULL; zbx_uint64_t mem_size = 0, byte_value = 0, total_memory; double pct_size = 0.0, pct_value = 0.0; int do_task, res, proccount = 0, invalid_user = 0, invalid_read = 0; int mem_type_tried = 0, mem_type_code; char *mem_type = NULL; const char *mem_type_search = NULL; if (5 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { errno = 0; if (NULL == (usrinfo = getpwnam(param))) { if (0 != errno) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain user information: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } invalid_user = 1; } } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "sum")) do_task = ZBX_DO_SUM; else if (0 == strcmp(param, "avg")) do_task = ZBX_DO_AVG; else if (0 == strcmp(param, "max")) do_task = ZBX_DO_MAX; else if (0 == strcmp(param, "min")) do_task = ZBX_DO_MIN; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } proccomm = get_rparam(request, 3); mem_type = get_rparam(request, 4); /* Comments for process memory types were compiled from: */ /* man 5 proc */ /* https://www.kernel.org/doc/Documentation/filesystems/proc.txt */ /* Himanshu Arora, Linux Processes explained - Part II, http://mylinuxbook.com/linux-processes-part2/ */ if (NULL == mem_type || '\0' == *mem_type || 0 == strcmp(mem_type, "vsize")) { mem_type_code = ZBX_VSIZE; /* current virtual memory size (total program size) */ mem_type_search = "VmSize:\t"; } else if (0 == strcmp(mem_type, "rss")) { mem_type_code = ZBX_RSS; /* current resident set size (size of memory portions) */ mem_type_search = "VmRSS:\t"; } else if (0 == strcmp(mem_type, "pmem")) { mem_type_code = ZBX_PMEM; /* percentage of real memory used by process */ } else if (0 == strcmp(mem_type, "size")) { mem_type_code = ZBX_SIZE; /* size of process (code + data + stack) */ } else if (0 == strcmp(mem_type, "peak")) { mem_type_code = ZBX_VMPEAK; /* peak virtual memory size */ mem_type_search = "VmPeak:\t"; } else if (0 == strcmp(mem_type, "swap")) { mem_type_code = ZBX_VMSWAP; /* size of swap space used */ mem_type_search = "VmSwap:\t"; } else if (0 == strcmp(mem_type, "lib")) { mem_type_code = ZBX_VMLIB; /* size of shared libraries */ mem_type_search = "VmLib:\t"; } else if (0 == strcmp(mem_type, "lck")) { mem_type_code = ZBX_VMLCK; /* size of locked memory */ mem_type_search = "VmLck:\t"; } else if (0 == strcmp(mem_type, "pin")) { mem_type_code = ZBX_VMPIN; /* size of pinned pages, they are never swappable */ mem_type_search = "VmPin:\t"; } else if (0 == strcmp(mem_type, "hwm")) { mem_type_code = ZBX_VMHWM; /* peak resident set size ("high water mark") */ mem_type_search = "VmHWM:\t"; } else if (0 == strcmp(mem_type, "data")) { mem_type_code = ZBX_VMDATA; /* size of data segment */ mem_type_search = "VmData:\t"; } else if (0 == strcmp(mem_type, "stk")) { mem_type_code = ZBX_VMSTK; /* size of stack segment */ mem_type_search = "VmStk:\t"; } else if (0 == strcmp(mem_type, "exe")) { mem_type_code = ZBX_VMEXE; /* size of text (code) segment */ mem_type_search = "VmExe:\t"; } else if (0 == strcmp(mem_type, "pte")) { mem_type_code = ZBX_VMPTE; /* size of page table entries */ mem_type_search = "VmPTE:\t"; } else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fifth parameter.")); return SYSINFO_RET_FAIL; } if (1 == invalid_user) /* handle 0 for non-existent user after all parameters have been parsed and validated */ goto out; if (ZBX_PMEM == mem_type_code) { if (SUCCEED != get_total_memory(&total_memory)) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain amount of total memory: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } if (0 == total_memory) /* this should never happen but anyway - avoid crash due to dividing by 0 */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Total memory reported is 0.")); return SYSINFO_RET_FAIL; } } if (NULL == (dir = opendir("/proc"))) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open /proc: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } while (NULL != (entries = readdir(dir))) { zbx_fclose(f_cmd); zbx_fclose(f_stat); if (0 == strcmp(entries->d_name, "self")) continue; zbx_snprintf(tmp, sizeof(tmp), "/proc/%s/cmdline", entries->d_name); if (NULL == (f_cmd = fopen(tmp, "r"))) continue; zbx_snprintf(tmp, sizeof(tmp), "/proc/%s/status", entries->d_name); if (NULL == (f_stat = fopen(tmp, "r"))) continue; if (FAIL == check_procname(f_cmd, f_stat, procname)) continue; if (FAIL == check_user(f_stat, usrinfo)) continue; if (FAIL == check_proccomm(f_cmd, proccomm)) continue; rewind(f_stat); if (0 == mem_type_tried) mem_type_tried = 1; switch (mem_type_code) { case ZBX_VSIZE: case ZBX_RSS: case ZBX_VMPEAK: case ZBX_VMSWAP: case ZBX_VMLIB: case ZBX_VMLCK: case ZBX_VMPIN: case ZBX_VMHWM: case ZBX_VMDATA: case ZBX_VMSTK: case ZBX_VMEXE: case ZBX_VMPTE: res = byte_value_from_proc_file(f_stat, mem_type_search, NULL, &byte_value); if (NOTSUPPORTED == res) continue; if (FAIL == res) { invalid_read = 1; goto clean; } break; case ZBX_SIZE: { zbx_uint64_t m; /* VmData, VmStk and VmExe follow in /proc/PID/status file in that order. */ /* Therefore we do not rewind f_stat between calls. */ mem_type_search = "VmData:\t"; if (SUCCEED == (res = byte_value_from_proc_file(f_stat, mem_type_search, NULL, &byte_value))) { mem_type_search = "VmStk:\t"; if (SUCCEED == (res = byte_value_from_proc_file(f_stat, mem_type_search, NULL, &m))) { byte_value += m; mem_type_search = "VmExe:\t"; if (SUCCEED == (res = byte_value_from_proc_file(f_stat, mem_type_search, NULL, &m))) { byte_value += m; } } } if (SUCCEED != res) { if (NOTSUPPORTED == res) { /* NOTSUPPORTED - at least one of data strings not found in */ /* the /proc/PID/status file */ continue; } else /* FAIL */ { invalid_read = 1; goto clean; } } } break; case ZBX_PMEM: mem_type_search = "VmRSS:\t"; res = byte_value_from_proc_file(f_stat, mem_type_search, NULL, &byte_value); if (SUCCEED == res) { pct_value = ((double)byte_value / (double)total_memory) * 100.0; } else if (NOTSUPPORTED == res) { continue; } else /* FAIL */ { invalid_read = 1; goto clean; } break; } if (ZBX_PMEM != mem_type_code) { if (0 != proccount++) { if (ZBX_DO_MAX == do_task) mem_size = MAX(mem_size, byte_value); else if (ZBX_DO_MIN == do_task) mem_size = MIN(mem_size, byte_value); else mem_size += byte_value; } else mem_size = byte_value; } else { if (0 != proccount++) { if (ZBX_DO_MAX == do_task) pct_size = MAX(pct_size, pct_value); else if (ZBX_DO_MIN == do_task) pct_size = MIN(pct_size, pct_value); else pct_size += pct_value; } else pct_size = pct_value; } } clean: zbx_fclose(f_cmd); zbx_fclose(f_stat); closedir(dir); if ((0 == proccount && 0 != mem_type_tried) || 0 != invalid_read) { char *s; s = zbx_strdup(NULL, mem_type_search); zbx_rtrim(s, ":\t"); SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot get amount of \"%s\" memory.", s)); zbx_free(s); return SYSINFO_RET_FAIL; } out: if (ZBX_PMEM != mem_type_code) { if (ZBX_DO_AVG == do_task) SET_DBL_RESULT(result, 0 == proccount ? 0 : (double)mem_size / (double)proccount); else SET_UI64_RESULT(result, mem_size); } else { if (ZBX_DO_AVG == do_task) SET_DBL_RESULT(result, 0 == proccount ? 0 : pct_size / (double)proccount); else SET_DBL_RESULT(result, pct_size); } return SYSINFO_RET_OK; #undef ZBX_SIZE #undef ZBX_RSS #undef ZBX_VSIZE #undef ZBX_PMEM #undef ZBX_VMPEAK #undef ZBX_VMSWAP #undef ZBX_VMLIB #undef ZBX_VMLCK #undef ZBX_VMPIN #undef ZBX_VMHWM #undef ZBX_VMDATA #undef ZBX_VMSTK #undef ZBX_VMEXE #undef ZBX_VMPTE }
int zbx_tcp_connect(zbx_sock_t *s, const char *source_ip, const char *ip, unsigned short port, int timeout ) { int ret = FAIL; struct addrinfo *ai = NULL, hints; struct addrinfo *ai_bind = NULL; char service[MAX_STRING_LEN]; ZBX_TCP_START(); zbx_tcp_clean(s); zbx_snprintf(service, sizeof(service), "%d", port); memset(&hints, 0x00, sizeof(struct addrinfo)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if (0 != getaddrinfo(ip, service, &hints, &ai)) { zbx_set_tcp_strerror("Cannot resolve [%s]", ip); goto out; } if (ZBX_SOCK_ERROR == (s->socket = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol))) { zbx_set_tcp_strerror("Cannot create socket [%s]:%d [%s]", ip, port ,strerror_from_system(zbx_sock_last_error())); goto out; } if (NULL != source_ip) { memset(&hints, 0x00, sizeof(struct addrinfo)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICHOST; if (0 != getaddrinfo(source_ip, NULL, &hints, &ai_bind)) { zbx_set_tcp_strerror("Invalid source IP address [%s]\n", source_ip); goto out; } if (ZBX_TCP_ERROR == bind(s->socket, ai_bind->ai_addr, ai_bind->ai_addrlen)) { zbx_set_tcp_strerror("bind() failed with error %d: %s\n", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error())); goto out; } } if (0 != timeout) { s->timeout = timeout; #if defined(_WINDOWS) timeout *= 1000; if (setsockopt(s->socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)) == ZBX_TCP_ERROR) zbx_set_tcp_strerror("setsockopt() failed with error %d: %s", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error())); if (setsockopt(s->socket, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout)) == ZBX_TCP_ERROR) zbx_set_tcp_strerror("setsockopt() failed with error %d: %s", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error())); #else alarm(timeout); #endif } if (ZBX_TCP_ERROR == connect(s->socket, ai->ai_addr, ai->ai_addrlen)) { zbx_set_tcp_strerror("*** Cannot connect to [%s]:%d [%s]", ip, port, strerror_from_system(zbx_sock_last_error())); zbx_tcp_close(s); goto out; } ret = SUCCEED; out: if (NULL != ai) freeaddrinfo(ai); if (NULL != ai_bind) freeaddrinfo(ai_bind); return ret; }
int PROC_NUM(AGENT_REQUEST *request, AGENT_RESULT *result) { char tmp[MAX_STRING_LEN], *procname, *proccomm, *param; DIR *dir; struct dirent *entries; struct passwd *usrinfo; FILE *f_cmd = NULL, *f_stat = NULL; int proccount = 0, invalid_user = 0, zbx_proc_stat; if (4 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { errno = 0; if (NULL == (usrinfo = getpwnam(param))) { if (0 != errno) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain user information: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } invalid_user = 1; } } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "all")) zbx_proc_stat = ZBX_PROC_STAT_ALL; else if (0 == strcmp(param, "run")) zbx_proc_stat = ZBX_PROC_STAT_RUN; else if (0 == strcmp(param, "sleep")) zbx_proc_stat = ZBX_PROC_STAT_SLEEP; else if (0 == strcmp(param, "zomb")) zbx_proc_stat = ZBX_PROC_STAT_ZOMB; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } proccomm = get_rparam(request, 3); if (1 == invalid_user) /* handle 0 for non-existent user after all parameters have been parsed and validated */ goto out; if (NULL == (dir = opendir("/proc"))) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open /proc: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } while (NULL != (entries = readdir(dir))) { zbx_fclose(f_cmd); zbx_fclose(f_stat); if (0 == strcmp(entries->d_name, "self")) continue; zbx_snprintf(tmp, sizeof(tmp), "/proc/%s/cmdline", entries->d_name); if (NULL == (f_cmd = fopen(tmp, "r"))) continue; zbx_snprintf(tmp, sizeof(tmp), "/proc/%s/status", entries->d_name); if (NULL == (f_stat = fopen(tmp, "r"))) continue; if (FAIL == check_procname(f_cmd, f_stat, procname)) continue; if (FAIL == check_user(f_stat, usrinfo)) continue; if (FAIL == check_proccomm(f_cmd, proccomm)) continue; if (FAIL == check_procstate(f_stat, zbx_proc_stat)) continue; proccount++; } zbx_fclose(f_cmd); zbx_fclose(f_stat); closedir(dir); out: SET_UI64_RESULT(result, proccount); return SYSINFO_RET_OK; }
/****************************************************************************** * * * Function: execute_action * * * * Purpose: execute an action depending on mediatype * * * * Parameters: alert - alert details * * mediatype - media details * * * * Return value: SUCCESS - action executed successfully * * FAIL - otherwise, error will contain error message * * * * Author: Alexei Vladishev * * * ******************************************************************************/ int execute_action(DB_ALERT *alert, DB_MEDIATYPE *mediatype, char *error, int max_error_len) { const char *__function_name = "execute_action"; int res = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s(): alertid [" ZBX_FS_UI64 "] mediatype [%d]", __function_name, alert->alertid, mediatype->type); if (MEDIA_TYPE_EMAIL == mediatype->type) { alarm(ALARM_ACTION_TIMEOUT); res = send_email(mediatype->smtp_server, mediatype->smtp_helo, mediatype->smtp_email, alert->sendto, alert->subject, alert->message, error, max_error_len); alarm(0); } #ifdef HAVE_JABBER else if (MEDIA_TYPE_JABBER == mediatype->type) { /* Jabber uses its own timeouts */ res = send_jabber(mediatype->username, mediatype->passwd, alert->sendto, alert->subject, alert->message, error, max_error_len); } #endif else if (MEDIA_TYPE_SMS == mediatype->type) { /* SMS uses its own timeouts */ res = send_sms(mediatype->gsm_modem, alert->sendto, alert->message, error, max_error_len); } else if (MEDIA_TYPE_EZ_TEXTING == mediatype->type) { /* Ez Texting uses its own timeouts */ res = send_ez_texting(mediatype->username, mediatype->passwd, alert->sendto, alert->message, mediatype->exec_path, error, max_error_len); } else if (MEDIA_TYPE_EXEC == mediatype->type) { char *cmd = NULL, *send_to, *subject, *message, *output = NULL; size_t cmd_alloc = ZBX_KIBIBYTE, cmd_offset = 0; cmd = zbx_malloc(cmd, cmd_alloc); zbx_snprintf_alloc(&cmd, &cmd_alloc, &cmd_offset, "%s/%s", CONFIG_ALERT_SCRIPTS_PATH, mediatype->exec_path); if (0 == access(cmd, X_OK)) { send_to = zbx_dyn_escape_string(alert->sendto, "\"\\"); subject = zbx_dyn_escape_string(alert->subject, "\"\\"); message = zbx_dyn_escape_string(alert->message, "\"\\"); zbx_snprintf_alloc(&cmd, &cmd_alloc, &cmd_offset, " \"%s\" \"%s\" \"%s\"", send_to, subject, message); zbx_free(send_to); zbx_free(subject); zbx_free(message); if (SUCCEED == (res = zbx_execute(cmd, &output, error, max_error_len, ALARM_ACTION_TIMEOUT))) { zabbix_log(LOG_LEVEL_DEBUG, "%s output:\n%s", mediatype->exec_path, output); zbx_free(output); } else res = FAIL; } else zbx_snprintf(error, max_error_len, "%s: %s", cmd, zbx_strerror(errno)); zbx_free(cmd); } else { zbx_snprintf(error, max_error_len, "unsupported media type [%d]", mediatype->type); zabbix_log(LOG_LEVEL_ERR, "alert ID [" ZBX_FS_UI64 "]: %s", alert->alertid, error); } zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(res)); return res; }
static int parse_response(DC_ITEM *items, AGENT_RESULT *results, int *errcodes, int num, char *response, char *error, int max_error_len) { const char *p; struct zbx_json_parse jp, jp_data, jp_row; char *value = NULL; size_t value_alloc = 0; int i, ret = GATEWAY_ERROR; if (SUCCEED == zbx_json_open(response, &jp)) { if (SUCCEED != zbx_json_value_by_name_dyn(&jp, ZBX_PROTO_TAG_RESPONSE, &value, &value_alloc)) { zbx_snprintf(error, max_error_len, "No '%s' tag in received JSON", ZBX_PROTO_TAG_RESPONSE); goto exit; } if (0 == strcmp(value, ZBX_PROTO_VALUE_SUCCESS)) { if (SUCCEED != zbx_json_brackets_by_name(&jp, ZBX_PROTO_TAG_DATA, &jp_data)) { zbx_strlcpy(error, "Cannot open data array in received JSON", max_error_len); goto exit; } p = NULL; for (i = 0; i < num; i++) { if (SUCCEED != errcodes[i]) continue; if (NULL == (p = zbx_json_next(&jp_data, p))) { zbx_strlcpy(error, "Not all values included in received JSON", max_error_len); goto exit; } if (SUCCEED != zbx_json_brackets_open(p, &jp_row)) { zbx_strlcpy(error, "Cannot open value object in received JSON", max_error_len); goto exit; } if (SUCCEED == zbx_json_value_by_name_dyn(&jp_row, ZBX_PROTO_TAG_VALUE, &value, &value_alloc)) { if (SUCCEED == set_result_type(&results[i], items[i].value_type, items[i].data_type, value)) errcodes[i] = SUCCEED; else errcodes[i] = NOTSUPPORTED; } else if (SUCCEED == zbx_json_value_by_name_dyn(&jp_row, ZBX_PROTO_TAG_ERROR, &value, &value_alloc)) { SET_MSG_RESULT(&results[i], zbx_strdup(NULL, value)); errcodes[i] = NOTSUPPORTED; } else { SET_MSG_RESULT(&results[i], zbx_strdup(NULL, "Cannot get item value or error message")); errcodes[i] = AGENT_ERROR; } } ret = SUCCEED; } else if (0 == strcmp(value, ZBX_PROTO_VALUE_FAILED)) { if (SUCCEED == zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_ERROR, error, max_error_len)) ret = NETWORK_ERROR; else zbx_strlcpy(error, "Cannot get error message describing reasons for failure", max_error_len); goto exit; } else { zbx_snprintf(error, max_error_len, "Bad '%s' tag value '%s' in received JSON", ZBX_PROTO_TAG_RESPONSE, value); goto exit; } } else { zbx_strlcpy(error, "Cannot open received JSON", max_error_len); goto exit; } exit: zbx_free(value); return ret; }