static int web_set_ip(AGENT_RESULT *result, struct web *opt, const char *params, int param_id) { char ip_tmp[WEB_MAX_DNS_STRLEN] = {0}; /* RFC1035 */ if (get_param(params, param_id, ip_tmp, WEB_MAX_DNS_STRLEN)) goto failed; zbx_remove_whitespace(ip_tmp); if (strlen(ip_tmp)) { if (!is_ip4(ip_tmp)) { opt->is_ipv6 = (zbx_uint64_t) 0; opt->ip = zbx_strdup(NULL, ip_tmp); return SUCCEED; } #if defined(HAVE_IPV6) else if (!is_ip6(ip_tmp)) { opt->is_ipv6 = (zbx_uint64_t) 1; opt->ip = zbx_strdup(NULL, ip_tmp); return SUCCEED; } #endif /*HAVE_IPV6*/ else if (!(zbx_check_hostname(ip_tmp))) { opt->is_ip_hostname = (zbx_uint64_t) 1; opt->host = zbx_strdup(NULL, ip_tmp); return SUCCEED; } else { goto failed; } } else { if (opt->item->interface.useip) { opt->ip = zbx_strdup(NULL, opt->item->interface.ip_orig); return SUCCEED; } else { opt->host = zbx_strdup(NULL, opt->item->interface.dns_orig); return web_resolv_dns(opt, opt->item->interface.dns_orig); } } failed: SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Invalid IP / DNS parameter", NULL)); return FAIL; }
static int process_ping(ZBX_FPING_HOST *hosts, int hosts_count, int count, int interval, int size, int timeout, char *error, int max_error_len) { const char *__function_name = "process_ping"; FILE *f; char *c, *c2, params[64]; char filename[MAX_STRING_LEN], tmp[MAX_STRING_LEN]; int i; ZBX_FPING_HOST *host; double sec; int ret = NOTSUPPORTED; #ifdef HAVE_IPV6 int family; char params6[64]; char fping_existence = 0; #define FPING_EXISTS 0x1 #define FPING6_EXISTS 0x2 #endif /* HAVE_IPV6 */ assert(hosts); zabbix_log(LOG_LEVEL_DEBUG, "In %s() hosts_count:%d", __function_name, hosts_count); if (-1 == access(CONFIG_FPING_LOCATION, F_OK | X_OK)) { #if !defined(HAVE_IPV6) zbx_snprintf(error, max_error_len, "%s: %s", CONFIG_FPING_LOCATION, zbx_strerror(errno)); return ret; #endif } else { #ifdef HAVE_IPV6 fping_existence |= FPING_EXISTS; #else if (NULL != CONFIG_SOURCE_IP) { if (FAIL == is_ip4(CONFIG_SOURCE_IP)) /* we do not have IPv4 family address in CONFIG_SOURCE_IP */ { zbx_snprintf(error, max_error_len, "You should enable IPv6 support to use IPv6 family address for SourceIP '%s'.", CONFIG_SOURCE_IP); return ret; } } #endif } #ifdef HAVE_IPV6 if (-1 == access(CONFIG_FPING6_LOCATION, F_OK | X_OK)) { if (0 == (fping_existence & FPING_EXISTS)) { zbx_snprintf(error, max_error_len, "At least one of '%s', '%s' must exist. Both are missing in the system.", CONFIG_FPING_LOCATION, CONFIG_FPING6_LOCATION); return ret; } } else fping_existence |= FPING6_EXISTS; #endif /* HAVE_IPV6 */ i = zbx_snprintf(params, sizeof(params), "-q -C%d", count); if (0 != interval) i += zbx_snprintf(params + i, sizeof(params) - i, " -p%d", interval); if (0 != size) i += zbx_snprintf(params + i, sizeof(params) - i, " -b%d", size); if (0 != timeout) i += zbx_snprintf(params + i, sizeof(params) - i, " -t%d", timeout); #ifdef HAVE_IPV6 strscpy(params6, params); #endif /* HAVE_IPV6 */ if (NULL != CONFIG_SOURCE_IP) { #ifdef HAVE_IPV6 if (0 != (fping_existence & FPING_EXISTS)) { if (0 == source_ip_checked) get_source_ip_option(CONFIG_FPING_LOCATION, &source_ip_option, &source_ip_checked); if (NULL != source_ip_option) zbx_snprintf(params + i, sizeof(params) - i, " %s%s", source_ip_option, CONFIG_SOURCE_IP); } if (0 != (fping_existence & FPING6_EXISTS)) { if (0 == source_ip6_checked) get_source_ip_option(CONFIG_FPING6_LOCATION, &source_ip6_option, &source_ip6_checked); if (NULL != source_ip6_option) zbx_snprintf(params6 + i, sizeof(params6) - i, " %s%s", source_ip6_option, CONFIG_SOURCE_IP); } #else if (0 == source_ip_checked) get_source_ip_option(CONFIG_FPING_LOCATION, &source_ip_option, &source_ip_checked); if (NULL != source_ip_option) zbx_snprintf(params + i, sizeof(params) - i, " %s%s", source_ip_option, CONFIG_SOURCE_IP); #endif /* HAVE_IPV6 */ } zbx_snprintf(filename, sizeof(filename), "%s/%s_%li.pinger", CONFIG_TMPDIR, progname, zbx_get_thread_id()); #ifdef HAVE_IPV6 if (NULL != CONFIG_SOURCE_IP) { if (SUCCEED != get_address_family(CONFIG_SOURCE_IP, &family, error, max_error_len)) return ret; if (family == PF_INET) { if (0 == (fping_existence & FPING_EXISTS)) { zbx_snprintf(error, max_error_len, "File '%s' cannot be found in the system.", CONFIG_FPING_LOCATION); return ret; } zbx_snprintf(tmp, sizeof(tmp), "%s %s 2>&1 <%s", CONFIG_FPING_LOCATION, params, filename); } else { if (0 == (fping_existence & FPING6_EXISTS)) { zbx_snprintf(error, max_error_len, "File '%s' cannot be found in the system.", CONFIG_FPING6_LOCATION); return ret; } zbx_snprintf(tmp, sizeof(tmp), "%s %s 2>&1 <%s", CONFIG_FPING6_LOCATION, params6, filename); } } else { i = 0; if (0 != (fping_existence & FPING_EXISTS)) i += zbx_snprintf(tmp + i, sizeof(tmp) - i, "%s %s 2>&1 <%s;", CONFIG_FPING_LOCATION, params, filename); if (0 != (fping_existence & FPING6_EXISTS)) i += zbx_snprintf(tmp + i, sizeof(tmp) - i, "%s %s 2>&1 <%s;", CONFIG_FPING6_LOCATION, params6, filename); } #else zbx_snprintf(tmp, sizeof(tmp), "%s %s 2>&1 <%s", CONFIG_FPING_LOCATION, params, filename); #endif /* HAVE_IPV6 */ if (NULL == (f = fopen(filename, "w"))) { zbx_snprintf(error, max_error_len, "%s: %s", filename, zbx_strerror(errno)); return ret; } zabbix_log(LOG_LEVEL_DEBUG, "%s", filename); for (i = 0; i < hosts_count; i++) { zabbix_log(LOG_LEVEL_DEBUG, "%s", hosts[i].addr); fprintf(f, "%s\n", hosts[i].addr); } fclose(f); zabbix_log(LOG_LEVEL_DEBUG, "%s", tmp); if (NULL == (f = popen(tmp, "r"))) { zbx_snprintf(error, max_error_len, "%s: %s", tmp, zbx_strerror(errno)); unlink(filename); return ret; } if (NULL == fgets(tmp, sizeof(tmp), f)) { ret = SUCCEED; /* fping does not output anything for DNS names that fail to resolve */ } else { do { zbx_rtrim(tmp, "\n"); zabbix_log(LOG_LEVEL_DEBUG, "read line [%s]", tmp); host = NULL; if (NULL != (c = strchr(tmp, ' '))) { *c = '\0'; for (i = 0; i < hosts_count; i++) if (0 == strcmp(tmp, hosts[i].addr)) { host = &hosts[i]; break; } *c = ' '; } if (NULL == host) continue; if (NULL == (c = strstr(tmp, " : "))) continue; /* when NIC bonding is used, there are also lines like */ /* 192.168.1.2 : duplicate for [0], 96 bytes, 0.19 ms */ if (NULL != strstr(tmp, "duplicate for")) continue; c += 3; do { if (NULL != (c2 = strchr(c, ' '))) *c2 = '\0'; if (0 != strcmp(c, "-")) { sec = atof(c) / 1000; /* convert ms to seconds */ if (host->rcv == 0 || host->min > sec) host->min = sec; if (host->rcv == 0 || host->max < sec) host->max = sec; host->avg = (host->avg * host->rcv + sec) / (host->rcv + 1); host->rcv++; } host->cnt++; if (NULL != c2) *c2++ = ' '; } while (NULL != (c = c2)); ret = SUCCEED; } while (NULL != fgets(tmp, sizeof(tmp), f)); } pclose(f); unlink(filename); if (NOTSUPPORTED == ret) zbx_snprintf(error, max_error_len, "fping failed: \"%s\"", tmp); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); return ret; }
int zbx_tcp_listen(zbx_sock_t *s, const char *listen_ip, unsigned short listen_port) { ZBX_SOCKADDR serv_addr; char *ip, *ips, *delim; int i, on, ret = FAIL; ZBX_TCP_START(); zbx_tcp_clean(s); ip = ips = (NULL == listen_ip ? NULL : strdup(listen_ip)); while (1) { delim = (NULL == ip ? NULL : strchr(ip, ',')); if (NULL != delim) *delim = '\0'; if (NULL != ip && FAIL == is_ip4(ip)) { zbx_set_tcp_strerror("incorrect IPv4 address [%s]", ip); goto out; } if (ZBX_SOCKET_COUNT == s->num_socks) { zbx_set_tcp_strerror("not enough space for socket [[%s]:%hu]", ip ? ip : "-", listen_port); goto out; } if (ZBX_SOCK_ERROR == (s->sockets[s->num_socks] = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0))) { zbx_set_tcp_strerror("socket() for [[%s]:%hu] failed: %s", ip ? ip : "-", listen_port, strerror_from_system(zbx_sock_last_error())); 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() for [[%s]:%hu] failed: %s", ip ? ip : "-", listen_port, strerror_from_system(zbx_sock_last_error())); } memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = NULL != ip ? inet_addr(ip) : htonl(INADDR_ANY); serv_addr.sin_port = htons((unsigned short)listen_port); if (ZBX_TCP_ERROR == bind(s->sockets[s->num_socks], (struct sockaddr *)&serv_addr, sizeof(serv_addr))) { zbx_set_tcp_strerror("bind() for [[%s]:%hu] failed: %s", ip ? ip : "-", listen_port, strerror_from_system(zbx_sock_last_error())); zbx_sock_close(s->sockets[s->num_socks]); goto out; } if (ZBX_TCP_ERROR == listen(s->sockets[s->num_socks], SOMAXCONN)) { zbx_set_tcp_strerror("listen() for [[%s]:%hu] failed: %s", ip ? ip : "-", listen_port, strerror_from_system(zbx_sock_last_error())); zbx_sock_close(s->sockets[s->num_socks]); goto out; } s->num_socks++; 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_ip : "-", listen_port); goto out; } ret = SUCCEED; out: if (NULL != ips) zbx_free(ips); if (SUCCEED != ret) { for (i = 0; i < s->num_socks; i++) zbx_sock_close(s->sockets[i]); } return ret; }
static int process_ping(ZBX_FPING_HOST *hosts, int hosts_count, int count, int interval, int size, int timeout, char *error, int max_error_len) { const char *__function_name = "process_ping"; FILE *f; char *c, params[64]; char filename[MAX_STRING_LEN], tmp[MAX_STRING_LEN]; size_t offset; ZBX_FPING_HOST *host; double sec; int i, ret = NOTSUPPORTED, index; #ifdef HAVE_IPV6 int family; char params6[64]; char fping_existence = 0; #define FPING_EXISTS 0x1 #define FPING6_EXISTS 0x2 #endif /* HAVE_IPV6 */ assert(hosts); zabbix_log(LOG_LEVEL_DEBUG, "In %s() hosts_count:%d", __function_name, hosts_count); if (-1 == access(CONFIG_FPING_LOCATION, X_OK)) { #if !defined(HAVE_IPV6) zbx_snprintf(error, max_error_len, "%s: %s", CONFIG_FPING_LOCATION, zbx_strerror(errno)); return ret; #endif } else { #ifdef HAVE_IPV6 fping_existence |= FPING_EXISTS; #else if (NULL != CONFIG_SOURCE_IP) { if (FAIL == is_ip4(CONFIG_SOURCE_IP)) /* we do not have IPv4 family address in CONFIG_SOURCE_IP */ { zbx_snprintf(error, max_error_len, "You should enable IPv6 support to use IPv6 family address for SourceIP '%s'.", CONFIG_SOURCE_IP); return ret; } } #endif } #ifdef HAVE_IPV6 if (-1 == access(CONFIG_FPING6_LOCATION, X_OK)) { if (0 == (fping_existence & FPING_EXISTS)) { zbx_snprintf(error, max_error_len, "At least one of '%s', '%s' must exist. Both are missing in the system.", CONFIG_FPING_LOCATION, CONFIG_FPING6_LOCATION); return ret; } } else fping_existence |= FPING6_EXISTS; #endif /* HAVE_IPV6 */ offset = zbx_snprintf(params, sizeof(params), "-C%d", count); if (0 != interval) offset += zbx_snprintf(params + offset, sizeof(params) - offset, " -p%d", interval); if (0 != size) offset += zbx_snprintf(params + offset, sizeof(params) - offset, " -b%d", size); if (0 != timeout) offset += zbx_snprintf(params + offset, sizeof(params) - offset, " -t%d", timeout); #ifdef HAVE_IPV6 strscpy(params6, params); #endif /* HAVE_IPV6 */ if (NULL != CONFIG_SOURCE_IP) { #ifdef HAVE_IPV6 if (0 != (fping_existence & FPING_EXISTS)) { if (0 == source_ip_checked) get_source_ip_option(CONFIG_FPING_LOCATION, &source_ip_option, &source_ip_checked); if (NULL != source_ip_option) zbx_snprintf(params + offset, sizeof(params) - offset, " %s%s", source_ip_option, CONFIG_SOURCE_IP); } if (0 != (fping_existence & FPING6_EXISTS)) { if (0 == source_ip6_checked) get_source_ip_option(CONFIG_FPING6_LOCATION, &source_ip6_option, &source_ip6_checked); if (NULL != source_ip6_option) zbx_snprintf(params6 + offset, sizeof(params6) - offset, " %s%s", source_ip6_option, CONFIG_SOURCE_IP); } #else if (0 == source_ip_checked) get_source_ip_option(CONFIG_FPING_LOCATION, &source_ip_option, &source_ip_checked); if (NULL != source_ip_option) zbx_snprintf(params + offset, sizeof(params) - offset, " %s%s", source_ip_option, CONFIG_SOURCE_IP); #endif /* HAVE_IPV6 */ } zbx_snprintf(filename, sizeof(filename), "%s/%s_%li.pinger", CONFIG_TMPDIR, progname, zbx_get_thread_id()); #ifdef HAVE_IPV6 if (NULL != CONFIG_SOURCE_IP) { if (SUCCEED != get_address_family(CONFIG_SOURCE_IP, &family, error, max_error_len)) return ret; if (family == PF_INET) { if (0 == (fping_existence & FPING_EXISTS)) { zbx_snprintf(error, max_error_len, "File '%s' cannot be found in the system.", CONFIG_FPING_LOCATION); return ret; } zbx_snprintf(tmp, sizeof(tmp), "%s %s 2>&1 <%s", CONFIG_FPING_LOCATION, params, filename); } else { if (0 == (fping_existence & FPING6_EXISTS)) { zbx_snprintf(error, max_error_len, "File '%s' cannot be found in the system.", CONFIG_FPING6_LOCATION); return ret; } zbx_snprintf(tmp, sizeof(tmp), "%s %s 2>&1 <%s", CONFIG_FPING6_LOCATION, params6, filename); } } else { offset = 0; if (0 != (fping_existence & FPING_EXISTS)) offset += zbx_snprintf(tmp + offset, sizeof(tmp) - offset, "%s %s 2>&1 <%s;", CONFIG_FPING_LOCATION, params, filename); if (0 != (fping_existence & FPING6_EXISTS)) zbx_snprintf(tmp + offset, sizeof(tmp) - offset, "%s %s 2>&1 <%s;", CONFIG_FPING6_LOCATION, params6, filename); } #else zbx_snprintf(tmp, sizeof(tmp), "%s %s 2>&1 <%s", CONFIG_FPING_LOCATION, params, filename); #endif /* HAVE_IPV6 */ if (NULL == (f = fopen(filename, "w"))) { zbx_snprintf(error, max_error_len, "%s: %s", filename, zbx_strerror(errno)); return ret; } zabbix_log(LOG_LEVEL_DEBUG, "%s", filename); for (i = 0; i < hosts_count; i++) { zabbix_log(LOG_LEVEL_DEBUG, " %s", hosts[i].addr); fprintf(f, "%s\n", hosts[i].addr); } fclose(f); zabbix_log(LOG_LEVEL_DEBUG, "%s", tmp); if (NULL == (f = popen(tmp, "r"))) { zbx_snprintf(error, max_error_len, "%s: %s", tmp, zbx_strerror(errno)); unlink(filename); return ret; } if (NULL == fgets(tmp, sizeof(tmp), f)) { ret = SUCCEED; /* fping does not output anything for DNS names that fail to resolve */ } else { for (i = 0; i < hosts_count; i++) { hosts[i].status = zbx_malloc(NULL, count); memset(hosts[i].status, 0, count); } do { zbx_rtrim(tmp, "\n"); zabbix_log(LOG_LEVEL_DEBUG, "read line [%s]", tmp); host = NULL; if (NULL != (c = strchr(tmp, ' '))) { *c = '\0'; for (i = 0; i < hosts_count; i++) if (0 == strcmp(tmp, hosts[i].addr)) { host = &hosts[i]; break; } *c = ' '; } if (NULL == host) continue; if (NULL == (c = strstr(tmp, " : "))) continue; /* when NIC bonding is used, there are also lines like */ /* 192.168.1.2 : duplicate for [0], 96 bytes, 0.19 ms */ if (NULL != strstr(tmp, "duplicate for")) continue; c += 3; /* The were two issues with processing only the fping's final status line: */ /* 1) pinging broadcast addresses could have resulted in responses from */ /* different hosts, which were counted as the target host responses; */ /* 2) there is a bug in fping (v3.8 at least) where pinging broadcast */ /* address will result in no individual responses, but the final */ /* status line might contain a bogus value. */ /* Because of the above issues we must monitor the individual responses */ /* and mark the valid ones. */ if ('[' == *c) { /* Fping appends response source address in format '[<- 10.3.0.10]' */ /* if it does not match the target address. Ignore such responses. */ if (NULL != strstr(c + 1, "[<-")) continue; /* get the index of individual ping response */ index = atoi(c + 1); if (0 > index || index >= count) continue; host->status[index] = 1; continue; } /* process status line for a host */ index = 0; do { if (1 == host->status[index]) { sec = atof(c) / 1000; /* convert ms to seconds */ if (0 == host->rcv || host->min > sec) host->min = sec; if (0 == host->rcv || host->max < sec) host->max = sec; host->avg = (host->avg * host->rcv + sec) / (host->rcv + 1); host->rcv++; } } while (++index < count && NULL != (c = strchr(c + 1, ' '))); host->cnt = count; ret = SUCCEED; } while (NULL != fgets(tmp, sizeof(tmp), f)); for (i = 0; i < hosts_count; i++) zbx_free(hosts[i].status); } pclose(f); unlink(filename); if (NOTSUPPORTED == ret) zbx_snprintf(error, max_error_len, "fping failed: \"%s\"", tmp); 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: * * * ******************************************************************************/ static int get_hostid_by_host(const char *host, const char *ip, unsigned short port, zbx_uint64_t *hostid, char *error) { const char *__function_name = "get_hostid_by_host"; char *host_esc, dns[INTERFACE_DNS_LEN_MAX]; DB_RESULT result; DB_ROW row; int res = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s() host:'%s'", __function_name, host); if (FAIL == zbx_check_hostname(host)) { zbx_snprintf(error, MAX_STRING_LEN, "invalid host name [%s]", host); goto out; } host_esc = DBdyn_escape_string(host); result = DBselect( "select hostid,status" " from hosts" " where host='%s'" " and status in (%d,%d)" " and proxy_hostid is null" DB_NODE, host_esc, HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED, DBnode_local("hostid")); if (NULL != (row = DBfetch(result))) { if (HOST_STATUS_MONITORED == atoi(row[1])) { ZBX_STR2UINT64(*hostid, row[0]); res = 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, (int)time(NULL)); } else if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY)) { DBproxy_register_host(host, ip, dns, port); } DBcommit(); } DBfree_result(result); zbx_free(host_esc); out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(res)); return res; }
/****************************************************************************** * * * 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 zbx_socket_t *sock, 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 = #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) DBselect( "select hostid,status,tls_accept,tls_issuer,tls_subject,tls_psk_identity" " 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); #else DBselect( "select hostid,status,tls_accept" " 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); #endif if (NULL != (row = DBfetch(result))) { if (HOST_STATUS_MONITORED == atoi(row[1])) { unsigned int tls_accept; tls_accept = (unsigned int)atoi(row[2]); if (0 == (tls_accept & sock->connection_type)) { zbx_snprintf(error, MAX_STRING_LEN, "connection of type \"%s\" is not allowed for host" " \"%s\"", zbx_tls_connection_type_name(sock->connection_type), host); goto done; } #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) if (ZBX_TCP_SEC_TLS_CERT == sock->connection_type) { zbx_tls_conn_attr_t attr; if (SUCCEED != zbx_tls_get_attr_cert(sock, &attr)) { THIS_SHOULD_NEVER_HAPPEN; zbx_snprintf(error, MAX_STRING_LEN, "cannot get connection attributes for host" " \"%s\"", host); goto done; } /* simplified match, not compliant with RFC 4517, 4518 */ if ('\0' != *row[3] && 0 != strcmp(row[3], attr.issuer)) { zbx_snprintf(error, MAX_STRING_LEN, "certificate issuer does not match for" " host \"%s\"", host); goto done; } /* simplified match, not compliant with RFC 4517, 4518 */ if ('\0' != *row[4] && 0 != strcmp(row[4], attr.subject)) { zbx_snprintf(error, MAX_STRING_LEN, "certificate subject does not match for" " host \"%s\"", host); goto done; } } else if (ZBX_TCP_SEC_TLS_PSK == sock->connection_type) { zbx_tls_conn_attr_t attr; if (SUCCEED != zbx_tls_get_attr_psk(sock, &attr)) { THIS_SHOULD_NEVER_HAPPEN; zbx_snprintf(error, MAX_STRING_LEN, "cannot get connection attributes for host" " \"%s\"", host); goto done; } if (strlen(row[5]) != attr.psk_identity_len || 0 != memcmp(row[5], attr.psk_identity, attr.psk_identity_len)) { zbx_snprintf(error, MAX_STRING_LEN, "false PSK identity for host \"%s\"", host); goto done; } } #endif 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; zbx_alarm_on(CONFIG_TIMEOUT); zbx_gethost_by_ip(ip, dns, sizeof(dns)); zbx_alarm_off(); DBbegin(); if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) DBregister_host(0, host, ip, dns, port, host_metadata, (int)time(NULL)); else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY)) DBproxy_register_host(host, ip, dns, port, host_metadata); DBcommit(); } done: 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; }