diff options
Diffstat (limited to 'src/libs/zbxcommon/misc.c')
-rw-r--r-- | src/libs/zbxcommon/misc.c | 478 |
1 files changed, 261 insertions, 217 deletions
diff --git a/src/libs/zbxcommon/misc.c b/src/libs/zbxcommon/misc.c index b1ace02e6aa..a6b30aede33 100644 --- a/src/libs/zbxcommon/misc.c +++ b/src/libs/zbxcommon/misc.c @@ -22,8 +22,39 @@ #include "setproctitle.h" #ifdef _WINDOWS + char ZABBIX_SERVICE_NAME[ZBX_SERVICE_NAME_LEN] = APPLICATION_NAME; char ZABBIX_EVENT_SOURCE[ZBX_SERVICE_NAME_LEN] = APPLICATION_NAME; + +int __zbx_stat(const char *path, zbx_stat_t *buf) +{ + int ret, fd; + wchar_t *wpath; + + wpath = zbx_utf8_to_unicode(path); + + if (-1 == (ret = _wstat64(wpath, buf))) + goto out; + + if (0 != S_ISDIR(buf->st_mode) || 0 != buf->st_size) + goto out; + + /* In the case of symlinks _wstat64 returns zero file size. */ + /* Try to work around it by opening the file and using fstat. */ + + ret = -1; + + if (-1 != (fd = _wopen(wpath, O_RDONLY))) + { + ret = _fstat64(fd, buf); + _close(fd); + } +out: + zbx_free(wpath); + + return ret; +} + #endif /****************************************************************************** @@ -223,7 +254,7 @@ void *zbx_calloc2(const char *filename, int line, void *old, size_t nmemb, si zabbix_log(LOG_LEVEL_CRIT, "[file:%s,line:%d] zbx_calloc: out of memory. Requested " ZBX_FS_SIZE_T " bytes.", filename, line, (zbx_fs_size_t)size); - exit(FAIL); + exit(EXIT_FAILURE); } /****************************************************************************** @@ -262,7 +293,7 @@ void *zbx_malloc2(const char *filename, int line, void *old, size_t size) zabbix_log(LOG_LEVEL_CRIT, "[file:%s,line:%d] zbx_malloc: out of memory. Requested " ZBX_FS_SIZE_T " bytes.", filename, line, (zbx_fs_size_t)size); - exit(FAIL); + exit(EXIT_FAILURE); } /****************************************************************************** @@ -294,7 +325,7 @@ void *zbx_realloc2(const char *filename, int line, void *old, size_t size) zabbix_log(LOG_LEVEL_CRIT, "[file:%s,line:%d] zbx_realloc: out of memory. Requested " ZBX_FS_SIZE_T " bytes.", filename, line, (zbx_fs_size_t)size); - exit(FAIL); + exit(EXIT_FAILURE); } char *zbx_strdup2(const char *filename, int line, char *old, const char *str) @@ -313,7 +344,7 @@ char *zbx_strdup2(const char *filename, int line, char *old, const char *str) zabbix_log(LOG_LEVEL_CRIT, "[file:%s,line:%d] zbx_strdup: out of memory. Requested " ZBX_FS_SIZE_T " bytes.", filename, line, (zbx_fs_size_t)(strlen(str) + 1)); - exit(FAIL); + exit(EXIT_FAILURE); } /****************************************************************************** @@ -845,67 +876,67 @@ int is_ip(const char *ip) /****************************************************************************** * * - * Function: expand_ipv6 * + * Function: ip6_str2dig * * * - * Purpose: convert short ipv6 addresses to expanded type * + * Purpose: convert short ipv6 addresses to the digital type * * * - * Parameters: ip - IPv6 IPs [12fc::2] * - * buf - result value [12fc:0000:0000:0000:0000:0000:0000:0002] * + * Parameters: ip - [IN] IPv6 IP address [12fc::2] * + * groups - [OUT] 8 groups of 16 bit each * + * 2001:0db8:0000:0000:0000:ff00:0042:8329 * * * * Return value: FAIL - invalid IP address, SUCCEED - conversion OK * * * - * Author: Alexander Vladishev * - * * ******************************************************************************/ -int expand_ipv6(const char *ip, char *str, size_t str_len) +int ip6_str2dig(const char *ip, unsigned short *groups) { - unsigned int i[8]; /* x:x:x:x:x:x:x:x */ - char buf[5], *ptr; - int c, dc, pos = 0, len; - size_t ip_len, j; + const char *ptr; + char buf[5]; + int c = 0, dc, pos = 0; + size_t ip_len, j, len; - c = 0; /* colons count */ - for (ptr = strchr(ip, ':'); ptr != NULL; ptr = strchr(ptr + 1, ':')) + for (ptr = strchr(ip, ':'); NULL != ptr; ptr = strchr(ptr + 1, ':')) c++; if (2 > c || c > 7) return FAIL; ip_len = strlen(ip); - if ((ip[0] == ':' && ip[1] != ':') || (ip[ip_len - 1] == ':' && ip[ip_len - 2] != ':')) + + if ((':' == ip[0] && ':' != ip[1]) || (':' == ip[ip_len - 1] && ':' != ip[ip_len - 2])) return FAIL; - memset(i, 0x00, sizeof(i)); + memset(groups, 0, sizeof(unsigned short) * 8); - dc = 0; /* double colon flag */ + dc = 0; /* double colon flag */ len = 0; + for (j = 0; j < ip_len; j++) { if (0 != isxdigit(ip[j])) { if (len > 3) return FAIL; - buf[len ++] = ip[j]; + buf[len++] = ip[j]; } - else if (ip[j] != ':') + else if (':' != ip[j]) return FAIL; - if (ip[j] == ':' || ip[j + 1] == '\0') + if (':' == ip[j] || '\0' == ip[j + 1]) { - if (len) + if (0 != len) { - buf[len] = 0x00; - sscanf(buf, "%x", &i[pos]); - pos ++; + buf[len] = '\0'; + sscanf(buf, "%hx", &groups[pos]); + pos++; len = 0; } - if (ip[j + 1] == ':') + if (':' == ip[j + 1]) { - if (dc == 0) + if (0 == dc) { dc = 1; - pos = ( 8 - c ) + pos + (j == 0 ? 1 : 0); + pos += (8 - c) + (0 == j); } else return FAIL; @@ -913,39 +944,31 @@ int expand_ipv6(const char *ip, char *str, size_t str_len) } } - zbx_snprintf(str, str_len, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", i[0], i[1], i[2], i[3], i[4], i[5], i[6], i[7]); - return SUCCEED; } #if defined(HAVE_IPV6) /****************************************************************************** * * - * Function: collapse_ipv6 * + * Function: ip6_dig2str * * * - * Purpose: convert array to IPv6 collapsed type * + * Purpose: convert ipv6 addresses to a string * * * - * Parameters: ip - [IN] full IPv6 address [12fc:0:0:0:0:0:0:2] * - * [OUT] short IPv6 address [12fc::0] * + * Parameters: groups - [IN] 8 groups of 16 bit each * + * ip - [OUT] short IPv6 address [12fc::0] * * ip_len - [IN] ip buffer len * * * * Return value: pointer to result buffer * * * - * Author: Alexander Vladishev * - * * ******************************************************************************/ -char *collapse_ipv6(char *str, size_t str_len) +void ip6_dig2str(unsigned short *groups, char *ip, size_t ip_len) { size_t offset = 0; int i, c = 0, m = 0, idx = -1, idx2 = -1; - unsigned int j[8]; - - if (8 != sscanf(str, "%x:%x:%x:%x:%x:%x:%x:%x", &j[0], &j[1], &j[2], &j[3], &j[4], &j[5], &j[6], &j[7])) - return str; for (i = 0; i <= 8; i++) { - if (i < 8 && j[i] == 0) + if (i < 8 && groups[i] == 0) { if (idx2 == -1) idx2 = i; @@ -965,23 +988,21 @@ char *collapse_ipv6(char *str, size_t str_len) for (i = 0; i < 8; i++) { - if (j[i] != 0 || idx == -1 || i < idx) + if (groups[i] != 0 || idx == -1 || i < idx) { - offset += zbx_snprintf(str + offset, str_len - offset, "%x", j[i]); + offset += zbx_snprintf(ip + offset, ip_len - offset, "%hx", groups[i]); if (i > idx) idx = -1; if (i < 7) - offset += zbx_snprintf(str + offset, str_len - offset, ":"); + offset += zbx_snprintf(ip + offset, ip_len - offset, ":"); } else if (idx == i) { - offset += zbx_snprintf(str + offset, str_len - offset, ":"); + offset += zbx_snprintf(ip + offset, ip_len - offset, ":"); if (idx == 0) - offset += zbx_snprintf(str + offset, str_len - offset, ":"); + offset += zbx_snprintf(ip + offset, ip_len - offset, ":"); } } - - return str; } /****************************************************************************** @@ -990,196 +1011,246 @@ char *collapse_ipv6(char *str, size_t str_len) * * * Purpose: check if ip matches range of ip addresses * * * - * Parameters: list - IPs [12fc::2-55,::45] * + * Parameters: list - [IN] comma-separated list of ip ranges * + * 12fc::2-55,::45,12fc::ff00/120 * + * ip - [IN] IPv6 ip address [12fc::2] * * * * Return value: FAIL - out of range, SUCCEED - within the range * * * - * Author: Alexei Vladishev * - * * ******************************************************************************/ -static int ip6_in_list(char *list, char *ip) +static int ip6_in_list(char *list, const char *ip) { - char *start, *comma = NULL, *dash = NULL, buffer[MAX_STRING_LEN]; - int i[8], j[9], ret = FAIL; + unsigned short i[8], j[9], mask; + char *start, *comma = NULL, *slash = NULL, *dash = NULL; + int ret = FAIL; - zabbix_log(LOG_LEVEL_DEBUG, "In ip6_in_list(list:%s,ip:%s)", list, ip); + if (FAIL == ip6_str2dig(ip, i)) + return FAIL; - if (FAIL == expand_ipv6(ip, buffer, sizeof(buffer))) + for (start = list; '\0' != *start;) { - goto out; - } + if (NULL != (comma = strchr(start, ','))) + *comma = '\0'; - if (sscanf(buffer, "%x:%x:%x:%x:%x:%x:%x:%x", &i[0], &i[1], &i[2], &i[3], &i[4], &i[5], &i[6], &i[7]) != 8) - { - goto out; - } + if (NULL != (dash = strchr(start, '-'))) + *dash = '\0'; + else if (NULL != (slash = strchr(start, '/'))) + *slash = '\0'; - for (start = list; start[0] != '\0';) - { + if (FAIL == ip6_str2dig(start, j)) + goto next; - if (NULL != (comma = strchr(start, ','))) + if (i[0] != j[0] || i[1] != j[1] || i[2] != j[2] || i[3] != j[3] || + i[4] != j[4] || i[5] != j[5] || i[6] != j[6]) { - comma[0] = '\0'; + goto next; } - if (NULL != (dash = strchr(start, '-'))) + if (NULL != dash) { - dash[0] = '\0'; - if (sscanf(dash + 1, "%x", &j[8]) != 1) - { + if (1 != sscanf(dash + 1, "%hx", &j[8])) goto next; - } } - - if (FAIL == expand_ipv6(start, buffer, sizeof(buffer))) + else if (NULL != slash) { - goto next; - } + if (1 != sscanf(slash + 1, "%hu", &j[8]) || 112 > j[8] || j[8] > 128) + goto next; - if (sscanf(buffer, "%x:%x:%x:%x:%x:%x:%x:%x", &j[0], &j[1], &j[2], &j[3], &j[4], &j[5], &j[6], &j[7]) != 8) - { - goto next; + mask = 0xffff << (128 - j[8]); + j[8] = j[7] | ~mask; + j[7] = j[7] & mask; } - - if (dash == NULL) - { + else j[8] = j[7]; - } - if (i[0] == j[0] && i[1] == j[1] && i[2] == j[2] && i[3] == j[3] && - i[4] == j[4] && i[5] == j[5] && i[6] == j[6] && - i[7] >= j[7] && i[7] <= j[8]) + if (i[7] >= j[7] && i[7] <= j[8]) { ret = SUCCEED; break; } next: - if (dash != NULL) + if (NULL != dash) { - dash[0] = '-'; + *dash = '-'; dash = NULL; } + else if (NULL != slash) + { + *slash = '/'; + slash = NULL; + } if (comma != NULL) { - comma[0] = ','; + *comma = ','; start = comma + 1; comma = NULL; } else - { break; - } } -out: + if (dash != NULL) - { - dash[0] = '-'; - } + *dash = '-'; + else if (slash != NULL) + *slash = '/'; if (comma != NULL) - { - comma[0] = ','; - } - - zabbix_log(LOG_LEVEL_DEBUG, "End of ip6_in_list():%s", - zbx_result_string(ret)); + *comma = ','; return ret; } -#endif /*HAVE_IPV6*/ +#endif /* HAVE_IPV6 */ /****************************************************************************** * * - * Function: ip_in_list * + * Function: ip4_str2dig * + * * + * Purpose: convert short ipv4 addresses to the digital type * + * * + * Parameters: ip - [IN] IPv4 IP address [192.168.0.1] * + * ip_dig - [OUT] 4-byte unsigned integer * + * * + * Return value: FAIL - invalid IP address, SUCCEED - conversion OK * + * * + ******************************************************************************/ +int ip4_str2dig(const char *ip, unsigned int *ip_dig) +{ + unsigned short i[4]; + + if (4 != sscanf(ip, "%hu.%hu.%hu.%hu", &i[0], &i[1], &i[2], &i[3])) + return FAIL; + + if (255 < i[0] || 255 < i[1] || 255 < i[2] || 255 < i[3]) + return FAIL; + + *ip_dig = (i[0] << 24) + (i[1] << 16) + (i[2] << 8) + i[3]; + + return SUCCEED; +} + +/****************************************************************************** + * * + * Function: ip4_in_list * * * * Purpose: check if ip matches range of ip addresses * * * - * Parameters: list - IPs [192.168.1.1-244,192.168.1.250] * + * Parameters: list - [IN] comma-separated list of ip ranges * + * 192.168.0.1-64,192.168.0.128,10.10.0.0/24 * + * ip - [IN] IPv4 ip address [192.168.0.1] * * * * Return value: FAIL - out of range, SUCCEED - within the range * * * - * Author: Alexei Vladishev * - * * ******************************************************************************/ -int ip_in_list(char *list, char *ip) +static int ip4_in_list(char *list, const char *ip) { - int i[4], j[5]; - int ret = FAIL; - char *start = NULL, *comma = NULL, *dash = NULL; - - zabbix_log( LOG_LEVEL_DEBUG, "In ip_in_list(list:%s,ip:%s)", list, ip); + unsigned short i; + unsigned int mask, ip_dig[2], first, last; + char *start = NULL, *comma = NULL, *slash = NULL, *dash = NULL; + int ret = FAIL; - if (sscanf(ip, "%d.%d.%d.%d", &i[0], &i[1], &i[2], &i[3]) != 4) - { -#if defined(HAVE_IPV6) - ret = ip6_in_list(list, ip); -#endif /*HAVE_IPV6*/ - goto out; - } + if (SUCCEED != ip4_str2dig(ip, &ip_dig[0])) + return FAIL; - for (start = list; start[0] != '\0';) + for (start = list; '\0' != *start;) { if (NULL != (comma = strchr(start, ','))) - { - comma[0] = '\0'; - } + *comma = '\0'; if (NULL != (dash = strchr(start, '-'))) + *dash = '\0'; + else if (NULL != (slash = strchr(start, '/'))) + *slash = '\0'; + + if (SUCCEED != ip4_str2dig(start, &ip_dig[1])) + goto next; + + if (NULL != dash) { - dash[0] = '\0'; - if (sscanf(dash + 1, "%d", &j[4]) != 1) - { + if (1 != sscanf(dash + 1, "%hu", &i) || 255 < i) goto next; - } - } - if (sscanf(start, "%d.%d.%d.%d", &j[0], &j[1], &j[2], &j[3]) != 4) - { - goto next; + first = ip_dig[1]; + last = (ip_dig[1] & 0xffffff00) + i; } + else if (NULL != slash) + { + if (1 != sscanf(slash + 1, "%hu", &i) || 16 > i || i > 30) + goto next; - if (dash == NULL) + mask = 0xffffffff << (32 - i); + first = (ip_dig[1] & mask) + 1; + last = (ip_dig[1] | ~mask) - 1; + } + else { - j[4] = j[3]; + first = ip_dig[1]; + last = ip_dig[1]; } - if (i[0] == j[0] && i[1] == j[1] && i[2] == j[2] && i[3] >= j[3] && i[3] <= j[4]) + if (first <= ip_dig[0] && ip_dig[0] <= last) { ret = SUCCEED; break; } next: - if (dash != NULL) + if (NULL != dash) { - dash[0] = '-'; + *dash = '-'; dash = NULL; } + else if (NULL != slash) + { + *slash = '/'; + slash = NULL; + } - if (comma != NULL) + if (NULL != comma) { - comma[0] = ','; + *comma = ','; start = comma + 1; comma = NULL; } else - { break; - } } -out: - if (dash != NULL) - { - dash[0] = '-'; - } + if (NULL != dash) + *dash = '-'; + else if (NULL != slash) + *slash = '/'; - if (comma != NULL) - { - comma[0] = ','; - } + if (NULL != comma) + *comma = ','; + + return ret; +} +/****************************************************************************** + * * + * Function: ip_in_list * + * * + * Purpose: check if ip matches range of ip addresses * + * * + * Parameters: ip - [IN] ip address * + * list - [IN] comma-separated list of ip ranges * + * 192.168.0.1-64,192.168.0.128,10.10.0.0/24,12fc:21 * + * * + * Return value: FAIL - out of range, SUCCEED - within the range * + * * + ******************************************************************************/ +int ip_in_list(char *list, const char *ip) +{ + const char *__function_name = "ip_in_list"; + + int ret = FAIL; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s() list:'%s' ip:'%s'", __function_name, list, ip); - zabbix_log(LOG_LEVEL_DEBUG, "End of ip_in_list():%s", - zbx_result_string(ret)); + ret = ip4_in_list(list, ip); +#if defined(HAVE_IPV6) + if (SUCCEED != ret) + ret = ip6_in_list(list, ip); +#endif + zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; } @@ -1248,6 +1319,11 @@ int int_in_list(char *list, int value) return ret; } +int zbx_double_compare(double a, double b) +{ + return fabs(a - b) < ZBX_DOUBLE_EPSILON ? SUCCEED : FAIL; +} + /****************************************************************************** * * * Function: is_double_suffix * @@ -1537,9 +1613,9 @@ int is_uint_n_range(const char *str, size_t n, void *value, size_t size, zbx_uin /* of 'value' buffer while on big endian architecture it will be stored starting from the last */ /* bytes. We handle it by storing the offset in the most significant byte of short value and */ /* then use the first byte as source offset. */ - unsigned short value_offset = (unsigned short)((sizeof(zbx_uint64_t) - size) << 8); + unsigned short value_offset = (unsigned short)((sizeof(zbx_uint64_t) - size) << 8); - memcpy(value, (unsigned char*)&value_uint64 + *((unsigned char*)&value_offset), size); + memcpy(value, (unsigned char *)&value_uint64 + *((unsigned char *)&value_offset), size); } return SUCCEED; @@ -1941,6 +2017,33 @@ void uint64_array_remove_both(zbx_uint64_t *values, int *num, zbx_uint64_t *rm_v } } +zbx_uint64_t suffix2factor(char c) +{ + switch (c) + { + case 'K': + return ZBX_KIBIBYTE; + case 'M': + return ZBX_MEBIBYTE; + case 'G': + return ZBX_GIBIBYTE; + case 'T': + return ZBX_TEBIBYTE; + case 's': + return 1; + case 'm': + return SEC_PER_MIN; + case 'h': + return SEC_PER_HOUR; + case 'd': + return SEC_PER_DAY; + case 'w': + return SEC_PER_WEEK; + default: + return 1; + } +} + /****************************************************************************** * * * Function: str2uint64 * @@ -1970,36 +2073,8 @@ int str2uint64(const char *str, const char *suffixes, zbx_uint64_t *value) if (NULL != strchr(suffixes, *p)) { - switch (*p) - { - case 'K': - factor = ZBX_KIBIBYTE; - break; - case 'M': - factor = ZBX_MEBIBYTE; - break; - case 'G': - factor = ZBX_GIBIBYTE; - break; - case 'T': - factor = ZBX_TEBIBYTE; - break; - case 's': - factor = 1; - break; - case 'm': - factor = SEC_PER_MIN; - break; - case 'h': - factor = SEC_PER_HOUR; - break; - case 'd': - factor = SEC_PER_DAY; - break; - case 'w': - factor = SEC_PER_WEEK; - break; - } + factor = suffix2factor(*p); + sz--; } @@ -2028,41 +2103,10 @@ int str2uint64(const char *str, const char *suffixes, zbx_uint64_t *value) double str2double(const char *str) { size_t sz; - double factor = 1; sz = strlen(str) - 1; - switch (str[sz]) - { - case 'K': - factor = ZBX_KIBIBYTE; - break; - case 'M': - factor = ZBX_MEBIBYTE; - break; - case 'G': - factor = ZBX_GIBIBYTE; - break; - case 'T': - factor = ZBX_TEBIBYTE; - break; - case 's': - break; - case 'm': - factor = SEC_PER_MIN; - break; - case 'h': - factor = SEC_PER_HOUR; - break; - case 'd': - factor = SEC_PER_DAY; - break; - case 'w': - factor = SEC_PER_WEEK; - break; - } - - return atof(str) * factor; + return atof(str) * suffix2factor(str[sz]); } /****************************************************************************** |