void drop_pid_file(const char *pidfile) { #ifdef HAVE_FCNTL_H struct flock fl; fl.l_type = F_UNLCK; /* tell it to unlock the region */ fl.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */ fl.l_start = 0; /* Offset from l_whence */ fl.l_len = 0; /* length, 0 = to EOF */ fl.l_pid = zbx_get_thread_id(); /* our PID */ #endif /* HAVE_FCNTL_H */ /* unlock file */ #ifdef HAVE_FCNTL_H if(-1 != fdpid) fcntl(fdpid, F_SETLK, &fl); #else if(-1 != fdpid) flock(fdpid, LOCK_UN); #endif /* HAVE_FCNTL_H */ /* close pid file */ zbx_fclose(fpid); if(-1 == unlink(pidfile)) { zabbix_log( LOG_LEVEL_DEBUG, "Cannot remove PID file [%s] [%s]", pidfile, strerror(errno)); } }
void drop_pid_file(const char *pidfile) { struct flock fl; fl.l_type = F_UNLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; fl.l_pid = zbx_get_thread_id(); /* unlock file */ if (-1 != fdpid) fcntl(fdpid, F_SETLK, &fl); /* close pid file */ zbx_fclose(fpid); unlink(pidfile); }
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 create_pid_file(const char *pidfile) { struct stat buf; int fd = 0; #ifdef HAVE_FCNTL_H struct flock fl; fl.l_type = F_WRLCK; /* F_RDLCK, F_WRLCK, F_UNLCK */ fl.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */ fl.l_start = 0; /* Offset from l_whence */ fl.l_len = 0; /* length, 0 = to EOF */ fl.l_pid = zbx_get_thread_id(); /* our PID */ #endif /* HAVE_FCNTL_H */ /* check if pid file already exists */ if(stat(pidfile,&buf) == 0) { #ifdef HAVE_FCNTL_H if( -1 == (fd = open(pidfile, O_WRONLY | O_APPEND))) #else if( -1 == (fd = open(pidfile, O_APPEND))) #endif /* HAVE_FCNTL_H */ { zbx_error("Cannot open PID file [%s] [%s]", pidfile, strerror(errno)); zabbix_log( LOG_LEVEL_CRIT, "Cannot open PID file [%s] [%s]", pidfile, strerror(errno)); return FAIL; } #ifdef HAVE_FCNTL_H if(-1 == fcntl(fd, F_SETLK, &fl) && EAGAIN == errno) #else if(-1 == flock(fd, LOCK_EX | LOCK_NB) && EWOULDBLOCK == errno) #endif /* HAVE_FCNTL_H */ { zbx_error("File [%s] exists and locked. Is this process already running ?", pidfile); zabbix_log( LOG_LEVEL_CRIT, "File [%s] exists and locked. Is this process already running ?", pidfile); return FAIL; } close(fd); } /* open pid file */ if( NULL == (fpid = fopen(pidfile, "w"))) { zbx_error("Cannot create PID file [%s] [%s]", pidfile, strerror(errno)); zabbix_log( LOG_LEVEL_CRIT, "Cannot create PID file [%s] [%s]", pidfile, strerror(errno)); return FAIL; } /* lock file */ fdpid = fileno(fpid); #ifdef HAVE_FCNTL_H if(-1 != fdpid) fcntl(fdpid, F_SETLK, &fl); #else if(-1 != fdpid) flock(fdpid, LOCK_EX); #endif /* HAVE_FCNTL_H */ /* frite pid to file */ fprintf(fpid, "%li", zbx_get_thread_id()); fflush(fpid); return SUCCEED; }
static int process_ping(ZBX_FPING_HOST *hosts, int hosts_count, char *error, int max_error_len) { FILE *f; char filename[MAX_STRING_LEN], tmp[MAX_STRING_LEN], *c, source_ip[64]; int i; ZBX_FPING_HOST *host; #ifdef HAVE_IPV6 char *fping; int family; #endif assert(hosts); zabbix_log(LOG_LEVEL_DEBUG, "In process_ping()"); if (NULL != CONFIG_SOURCE_IP) zbx_snprintf(source_ip, sizeof(source_ip), "-S%s ", CONFIG_SOURCE_IP); else *source_ip = '\0'; if (access(CONFIG_FPING_LOCATION, F_OK|X_OK) == -1) { zbx_snprintf(error, max_error_len, "%s: [%d] %s", CONFIG_FPING_LOCATION, errno, strerror(errno)); return NOTSUPPORTED; } zbx_snprintf(filename, sizeof(filename), "%s/zabbix_server_%li.pinger", CONFIG_TMPDIR, zbx_get_thread_id()); #ifdef HAVE_IPV6 if (access(CONFIG_FPING6_LOCATION, F_OK|X_OK) == -1) { zbx_snprintf(error, max_error_len, "%s: [%d] %s", CONFIG_FPING6_LOCATION, errno, strerror(errno)); return NOTSUPPORTED; } if (NULL != CONFIG_SOURCE_IP) { if (NOTSUPPORTED == get_address_family(CONFIG_SOURCE_IP, &family, error, max_error_len)) return NOTSUPPORTED; if (family == PF_INET) fping = CONFIG_FPING_LOCATION; else fping = CONFIG_FPING6_LOCATION; zbx_snprintf(tmp, sizeof(tmp), "%s %s-c3 2>/dev/null <%s", fping, source_ip, filename); } else zbx_snprintf(tmp, sizeof(tmp), "%s -c3 2>/dev/null <%s;%s -c3 2>/dev/null <%s", CONFIG_FPING_LOCATION, filename, CONFIG_FPING6_LOCATION, filename); #else /* HAVE_IPV6 */ zbx_snprintf(tmp, sizeof(tmp), "%s %s-c3 2>/dev/null <%s", CONFIG_FPING_LOCATION, source_ip, filename); #endif /* HAVE_IPV6 */ if (NULL == (f = fopen(filename, "w"))) { zbx_snprintf(error, max_error_len, "%s: [%d] %s", filename, errno, strerror(errno)); return NOTSUPPORTED; } 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 (0 == (f = popen(tmp, "r"))) { zbx_snprintf(error, max_error_len, "%s: [%d] %s", tmp, errno, strerror(errno)); unlink(filename); return NOTSUPPORTED; } while (NULL != fgets(tmp, sizeof(tmp), f)) { zbx_rtrim(tmp, "\n"); zabbix_log(LOG_LEVEL_DEBUG, "Update IP [%s]", tmp); /* 12fc::21 : [0], 76 bytes, 0.39 ms (0.39 avg, 0% loss) */ 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; } } if (NULL != host) { c++; if (NULL != (c = strchr(c, '('))) { c++; host->alive = 1; host->sec = atof(c)/1000; } } } pclose(f); unlink(filename); zabbix_log(LOG_LEVEL_DEBUG, "End of process_ping()"); return SUCCEED; }
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; }