Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/zbxcommon/misc.c')
-rw-r--r--src/libs/zbxcommon/misc.c478
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]);
}
/******************************************************************************