diff options
author | sasha <sasha@97f52cf1-0a1b-0410-bd0e-c28be96e8082> | 2007-09-17 09:35:13 +0000 |
---|---|---|
committer | sasha <sasha@97f52cf1-0a1b-0410-bd0e-c28be96e8082> | 2007-09-17 09:35:13 +0000 |
commit | 2ae95f35e566afdee93ea06bbf02443257ce7716 (patch) | |
tree | 0eddf35ca439ddc34473ffe97fce4615705017ad | |
parent | cb2c5743fee519c1490317552b98a09f48daf92a (diff) | |
download | zabbix-2ae95f35e566afdee93ea06bbf02443257ce7716.tar.gz zabbix-2ae95f35e566afdee93ea06bbf02443257ce7716.tar.xz zabbix-2ae95f35e566afdee93ea06bbf02443257ce7716.zip |
[DEV-23] improvements in configure.in IPv6 (Sasha)
[DEV-23] Autodiscovery for IPv6 (Sasha)
[DEV-17] Add support of IPv6 to standard library (comms.c) (Sasha)
[DEV-21] extended size of IP fields to accept IPv6 style IPs (Alexei)
[DEV-21] added basic validation of IPv6 IP addresses in GUI (Alexei)
[DEV-18] Modified structures of include/db.h to have larger length for IP addresses.
[DEV-18] database schema enhanced for IPv6 addresses (Alexei)
Minor fix for confgure.in.
support of --enable-ipv6 for configure.in (Alexei)
git-svn-id: svn://svn.zabbix.com/trunk@4752 97f52cf1-0a1b-0410-bd0e-c28be96e8082
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | configure.in | 28 | ||||
-rw-r--r-- | create/schema/schema.sql | 6 | ||||
-rw-r--r-- | frontends/php/include/defines.inc.php | 2 | ||||
-rw-r--r-- | frontends/php/include/forms.inc.php | 9 | ||||
-rw-r--r-- | frontends/php/include/validate.inc.php | 89 | ||||
-rwxr-xr-x | go | 2 | ||||
-rw-r--r-- | include/comms.h | 3 | ||||
-rw-r--r-- | include/db.h | 4 | ||||
-rw-r--r-- | src/alphacode/poller/poller.c | 3 | ||||
-rw-r--r-- | src/libs/zbxcommon/misc.c | 275 | ||||
-rw-r--r-- | src/libs/zbxcomms/comms.c | 250 | ||||
-rw-r--r-- | src/libs/zbxemail/email.c | 176 | ||||
-rw-r--r-- | src/zabbix_server/discoverer/discoverer.c | 87 | ||||
-rw-r--r-- | src/zabbix_server/operations.c | 36 | ||||
-rw-r--r-- | src/zabbix_server/server.c | 128 |
16 files changed, 842 insertions, 262 deletions
@@ -13,6 +13,12 @@ Changes for 1.5: Changes for 1.4.3: + - [DEV-23] Autodiscovery for IPv6 (Sasha) + - [DEV-17] Add support of IPv6 to standard library (comms.c) (Sasha) + - [DEV-21] extended size of IP fields to accept IPv6 style IPs (Alexei) + - [DEV-21] added basic validation of IPv6 IP addresses in GUI (Alexei) + - [DEV-18] database schema enhanced for IPv6 addresses (Alexei) + - [DEV-20] support of --enable-ipv6 for configure.in (Alexei) - [NTT-16] added synchronisation of last value and timestamp for DM (Alexei) - [ZBX-1] fixed wrong status of function "nodata" after server restart (Sasha) - [ZBX-33] fixed problem in table names in data.sql for PostgreSQL (Sasha) diff --git a/configure.in b/configure.in index 42540c32..122676fb 100644 --- a/configure.in +++ b/configure.in @@ -547,11 +547,25 @@ esac], [agent=no]) AM_CONDITIONAL(AGENT, test x$agent = xyes) +AC_ARG_ENABLE(ipv6,[ --enable-ipv6 Turn on support of IPv6], +[case "${enableval}" in + yes) ipv6=yes ;; + no) ipv6=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-ipv6]) ;; +esac], +[ipv6=no]) + have_db="no" have_odbc="no" have_web_monitoring="no" have_jabber="no" have_snmp="no" +have_ipv6="no" + +if test "$ipv6" = "yes"; then + AC_DEFINE(HAVE_IPV6,1,[Define to 1 if IPv6 should be enabled.]) + have_ipv6="yes" +fi if test "$server" = "yes"; then @@ -923,13 +937,13 @@ Configuration: if test "x$server" != "xno"; then -echo " With database: ${have_db} - Enable DB monitor via: ${have_odbc} - WEB Monitoring via: ${have_web_monitoring} - Native Jabber: ${have_jabber} - SNMP: ${have_snmp} - Linker flags: ${LDFLAGS} ${SERVER_LDFLAGS} - Libraries: ${LIBS} ${SERVER_LIBS}" +echo " With database: ${have_db} + WEB Monitoring via: ${have_web_monitoring} + Native Jabber: ${have_jabber} + SNMP: ${have_snmp} + IPv6: ${have_ipv6} + Linker flags: ${LDFLAGS} ${SERVER_LDFLAGS} + Libraries: ${LIBS} ${SERVER_LIBS}" fi diff --git a/create/schema/schema.sql b/create/schema/schema.sql index 26fd43e8..31da1288 100644 --- a/create/schema/schema.sql +++ b/create/schema/schema.sql @@ -53,7 +53,7 @@ FIELD |ports |t_varchar(255) |'0' |NOT NULL |ZBX_SYNC TABLE|dhosts|dhostid|ZBX_SYNC FIELD |dhostid |t_id |'0' |NOT NULL |ZBX_SYNC FIELD |druleid |t_id |'0' |NOT NULL |ZBX_SYNC -FIELD |ip |t_varchar(15) |'' |NOT NULL |ZBX_SYNC +FIELD |ip |t_varchar(39) |'' |NOT NULL |ZBX_SYNC FIELD |status |t_integer |'0' |NOT NULL |ZBX_SYNC FIELD |lastup |t_integer |'0' |NOT NULL |ZBX_SYNC FIELD |lastdown |t_integer |'0' |NOT NULL |ZBX_SYNC @@ -122,7 +122,7 @@ TABLE|nodes|nodeid| FIELD |nodeid |t_integer |'0' |NOT NULL |0 FIELD |name |t_varchar(64) |'0' |NOT NULL |0 FIELD |timezone |t_integer |'0' |NOT NULL |ZBX_SYNC -FIELD |ip |t_varchar(15) |'' |NOT NULL |ZBX_SYNC +FIELD |ip |t_varchar(39) |'' |NOT NULL |ZBX_SYNC FIELD |port |t_integer |'10051'|NOT NULL |ZBX_SYNC FIELD |slave_history |t_integer |'30' |NOT NULL |ZBX_SYNC FIELD |slave_trends |t_integer |'365' |NOT NULL |ZBX_SYNC @@ -381,7 +381,7 @@ FIELD |hostid |t_id |'0' |NOT NULL |ZBX_SYNC FIELD |host |t_varchar(64) |'' |NOT NULL |ZBX_SYNC FIELD |dns |t_varchar(64) |'' |NOT NULL |ZBX_SYNC FIELD |useip |t_integer |'1' |NOT NULL |ZBX_SYNC -FIELD |ip |t_varchar(15) |'127.0.0.1'|NOT NULL |ZBX_SYNC +FIELD |ip |t_varchar(39) |'127.0.0.1'|NOT NULL |ZBX_SYNC FIELD |port |t_integer |'10050'|NOT NULL |ZBX_SYNC FIELD |status |t_integer |'0' |NOT NULL |ZBX_SYNC FIELD |disable_until |t_integer |'0' |NOT NULL |0 diff --git a/frontends/php/include/defines.inc.php b/frontends/php/include/defines.inc.php index d52df3c4..8360dd51 100644 --- a/frontends/php/include/defines.inc.php +++ b/frontends/php/include/defines.inc.php @@ -437,6 +437,8 @@ /* Define if your logs are in non-standard format */ /* define('ZBX_LOG_ENCODING_DEFAULT', 'Shift_JIS');*/ + define('ZBX_HAVE_IPV6', 1); + global $_GET, $_POST, $_COOKIE, $_REQUEST; /* Support for PHP5. PHP5 does not have $HTTP_..._VARS */ diff --git a/frontends/php/include/forms.inc.php b/frontends/php/include/forms.inc.php index a92aafae..2589473e 100644 --- a/frontends/php/include/forms.inc.php +++ b/frontends/php/include/forms.inc.php @@ -4087,7 +4087,14 @@ include_once 'include/discovery.inc.php'; else { $frmHost->AddRow(S_DNS_NAME,new CTextBox("dns",$dns,"40")); - $frmHost->AddRow(S_IP_ADDRESS,new CTextBox("ip",$ip,"15")); + if(defined('ZBX_HAVE_IPV6')) + { + $frmHost->AddRow(S_IP_ADDRESS,new CTextBox("ip",$ip,"39")); + } + else + { + $frmHost->AddRow(S_IP_ADDRESS,new CTextBox("ip",$ip,"15")); + } $cmbConnectBy = new CComboBox('useip', $useip); $cmbConnectBy->AddItem(0, S_DNS_NAME); diff --git a/frontends/php/include/validate.inc.php b/frontends/php/include/validate.inc.php index 997e7f76..a628744f 100644 --- a/frontends/php/include/validate.inc.php +++ b/frontends/php/include/validate.inc.php @@ -70,15 +70,41 @@ { return 'ereg(\'^([0-9a-zA-Z\_\.[.-.]\$ ]+)$\',{'.$var.'})&&'; } - - function validate_ip($str,&$arr) + function validate_ipv4($str,&$arr) { if( !ereg('^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$', $str, $arr) ) return false; for($i=1; $i<=4; $i++) if( !is_numeric($arr[$i]) || $arr[$i] > 255 || $arr[$i] < 0 ) return false; return true; } + function validate_ipv6($str,&$arr) + { + $pattern1 = '([A-Fa-f0-9]{1,4}:){7}[A-Fa-f0-9]{1,4}'; + $pattern2 = ':(:[A-Fa-f0-9]{1,4}){1,7}'; + $pattern3 = '[A-Fa-f0-9]{1,4}::([A-Fa-f0-9]{1,4}:){0,5}[A-Fa-f0-9]{1,4}'; + $pattern4 = '([A-Fa-f0-9]{1,4}:){2}:([A-Fa-f0-9]{1,4}:){0,4}[A-Fa-f0-9]{1,4}'; + $pattern5 = '([A-Fa-f0-9]{1,4}:){3}:([A-Fa-f0-9]{1,4}:){0,3}[A-Fa-f0-9]{1,4}'; + $pattern6 = '([A-Fa-f0-9]{1,4}:){4}:([A-Fa-f0-9]{1,4}:){0,2}[A-Fa-f0-9]{1,4}'; + $pattern7 = '([A-Fa-f0-9]{1,4}:){5}:([A-Fa-f0-9]{1,4}:){0,1}[A-Fa-f0-9]{1,4}'; + $pattern8 = '([A-Fa-f0-9]{1,4}:){6}:[A-Fa-f0-9]{1,4}'; + + $full = "/^($pattern1)$|^($pattern2)$|^($pattern3)$|^($pattern4)$|^($pattern5)$|^($pattern6)$|^($pattern7)$|^($pattern8)$/"; + + if( !ereg($full, $str, $arr) ) return false; + return true; + } - function validate_ip_range($str) + function validate_ip($str,&$arr) + { + if(validate_ipv4($str,&$arr)) + return true; + if(defined('ZBX_HAVE_IPV6')) + { + return validate_ipv6($str,&$arr); + } + return false; + } + +/* function validate_ip_range($str) { foreach(explode(',',$str) as $ip_range) { @@ -100,7 +126,64 @@ } return true; } +*/ + function validate_ip_range($str) + { + foreach(explode(',',$str) as $ip_range) + { + $parts = explode('-', $ip_range); + $parts_count = count($parts); + if($parts_count > 2) return false; + + if(validate_ipv4($parts[0], $arr)) + { + $ip_parts = explode('.', $parts[0]); + + if( $parts_count == 2 ) + { + if( !ereg('^[0-9]{1,3}$', $parts[1]) ) return false; + + sscanf($ip_parts[3], "%d", $from_value); + sscanf($parts[1], "%d", $to_value); + if($to_value > 255 || $from_value > $to_value) return false; + } + } + else if( defined('ZBX_HAVE_IPV6') && validate_ipv6($parts[0], $arr) ) + { + $ip_parts = explode(':', $parts[0]); + $ip_parts_count = count($ip_parts); + + if( $parts_count == 2 ) + { + if( !ereg('^[A-Fa-f0-9]{1,4}$', $parts[1]) ) return false; + + sscanf($ip_parts[$ip_parts_count - 1], "%x", $from_value); + sscanf($parts[1], "%x", $to_value); + if($from_value > $to_value) return false; + } + } + else + { + return false; + } + + } + return true; + } +/* function validate_ip_range($str) + { + if(defined('ZBX_HAVE_IPV6')) + { + return validate_ipv4_ipv6_range($str); + } + else + { + return validate_ipv4_range($str); + } + return false; + } +*/ function validate_port_list($str) { foreach(explode(',',$str) as $port_range) @@ -33,7 +33,7 @@ cd - #export CFLAGS="-Wall -pedantic" #for db in sqlite3 pgsql mysql; do for db in mysql; do - ./configure --enable-agent --with-net-snmp --with-libcurl --with-ldap --enable-server --with-$db --prefix=`pwd` 2>>WARNINGS >/dev/null + ./configure --enable-agent --enable-server --with-jabber --with-ldap --with-libcurl --with-$db --with-net-snmp --prefix=`pwd` --enable-ipv6 2>>WARNINGS >/dev/null echo Cleaning... make clean 2>>WARNINGS >/dev/null echo Making... diff --git a/include/comms.h b/include/comms.h index 50ecde1f..29fe4f69 100644 --- a/include/comms.h +++ b/include/comms.h @@ -32,6 +32,7 @@ typedef enum { typedef int ZBX_SOCKET; #endif /* SOCKET || _WINDOWS */ + typedef struct sockaddr_in ZBX_SOCKADDR; typedef enum @@ -59,7 +60,7 @@ int zbx_tcp_error(void); struct hostent *zbx_gethost(const char *hostname); #if !defined(_WINDOWS) -struct hostent *zbx_gethost_by_ip(const char *ip); +void zbx_gethost_by_ip(const char *ip, char *host, size_t hostlen); #endif /* WINDOWS */ void zbx_tcp_init(zbx_sock_t *s, ZBX_SOCKET o); diff --git a/include/db.h b/include/db.h index e2937c57..f8a371af 100644 --- a/include/db.h +++ b/include/db.h @@ -104,7 +104,7 @@ typedef enum { #define MAX_HOST_HOST_LEN 64 #define MAX_ITEM_KEY_LEN 255 -#define MAX_ITEM_IP_LEN 15 +#define MAX_ITEM_IP_LEN 39 #define MAX_ITEM_SNMP_COMMUNITY_LEN 64 #define MAX_ITEM_SNMP_OID_LEN 255 @@ -127,7 +127,7 @@ typedef enum { #define HOST_HOST_LEN_MAX HOST_HOST_LEN+1 #define HOST_DNS_LEN 64 #define HOST_DNS_LEN_MAX HOST_DNS_LEN+1 -#define HOST_IP_LEN 15 +#define HOST_IP_LEN 39 #define HOST_IP_LEN_MAX HOST_IP_LEN+1 #define HOST_ERROR_LEN 128 #define HOST_ERROR_LEN_MAX HOST_ERROR_LEN+1 diff --git a/src/alphacode/poller/poller.c b/src/alphacode/poller/poller.c index ad24290f..b86f8e3c 100644 --- a/src/alphacode/poller/poller.c +++ b/src/alphacode/poller/poller.c @@ -170,14 +170,13 @@ int main() for(i=0;i<NUM;i++) { - servaddr_in.sin_family=AF_INET; if(NULL == (hp = zbx_gethost(ip))) { perror("gethost() failed"); } + servaddr_in.sin_family=AF_INET; servaddr_in.sin_addr.s_addr=((struct in_addr *)(hp->h_addr))->s_addr; - servaddr_in.sin_port=htons(port); s=socket(AF_INET,SOCK_STREAM,0); diff --git a/src/libs/zbxcommon/misc.c b/src/libs/zbxcommon/misc.c index d0178da4..9f004783 100644 --- a/src/libs/zbxcommon/misc.c +++ b/src/libs/zbxcommon/misc.c @@ -233,6 +233,203 @@ int calculate_item_nextcheck(zbx_uint64_t itemid, int item_type, int delay, char return i; } +#if defined(HAVE_IPV6) +/****************************************************************************** + * * + * Function: expand_ipv6 * + * * + * Purpose: convert short ipv6 addresses to expanded type * + * * + * Parameters: ip - IPv6 IPs [12fc::2] * + * buf - result value [12fc:0000:0000:0000:0000:0000:0000:0002] * + * * + * Return value: FAIL - invlid IP address, SUCCEED - conversion OK * + * * + * Author: Alksander Vladishev * + * * + * Comments: * + * * + ******************************************************************************/ +int expand_ipv6(const char *ip, char *str, size_t str_len ) +{ + unsigned int i[8]; /* x:x:x:x:x:x:x:x */ + char buf[5], *ptr; + int c, dc, pos = 0, j, len, ip_len, ret = FAIL; + + zabbix_log(LOG_LEVEL_DEBUG, "In expand_ipv6(ip:%s)", ip); + + c = 0; /* colons count */ + for(ptr = strchr(ip, ':'); ptr != NULL; ptr = strchr(ptr + 1, ':')) + { + c ++; + } + + if(c < 2 || c > 7) + { + goto out; + } + + ip_len = strlen(ip); + if((ip[0] == ':' && ip[1] != ':') || (ip[ip_len - 1] == ':' && ip[ip_len - 2] != ':')) + { + goto out; + } + + memset(i, 0x00, sizeof(i)); + + dc = 0; /* double colon flag */ + len = 0; + for(j = 0; j<ip_len; j++) + { + if((ip[j] >= '0' && ip[j] <= '9') || (ip[j] >= 'A' && ip[j] <= 'F') || (ip[j] >= 'a' && ip[j] <= 'f')) + { + if(len > 3) + { + goto out; + } + buf[len ++] = ip[j]; + } + else if(ip[j] != ':') + { + goto out; + } + + if(ip[j] == ':' || ip[j + 1] == '\0') + { + if(len) + { + buf[len] = 0x00; + sscanf(buf, "%x", &i[pos]); + pos ++; + len = 0; + } + + if(ip[j + 1] == ':') + { + if(dc == 0) + { + dc = 1; + pos = ( 8 - c ) + pos + (j == 0 ? 1 : 0); + } + else + { + goto out; + } + } + } + } + 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]); + ret = SUCCEED; +out: + zabbix_log(LOG_LEVEL_DEBUG, "End expand_ipv6(ip:%s,str:%s,ret:%s)", ip, str, ret == SUCCEED ? "SUCCEED" : "FAIL"); + + return ret; +} + +/****************************************************************************** + * * + * Function: ip_in_list_ipv6 * + * * + * Purpose: check if ip matches range of ip addresses * + * * + * Parameters: list - IPs [12fc::2-55,::45] * + * * + * Return value: FAIL - out of range, SUCCEED - within the range * + * * + * Author: Alexei Vladishev * + * * + * Comments: * + * * + ******************************************************************************/ +int ip_in_list_ipv6(char *list, char *ip) +{ + char *start, *comma = NULL, *dash = NULL, buffer[MAX_STRING_LEN]; + int i[8], j[9], ret = FAIL; + + zabbix_log(LOG_LEVEL_DEBUG, "In ip_in_list(list:%s,ip:%s)", list, ip); + + if(FAIL == expand_ipv6(ip, buffer, sizeof(buffer))) + { + goto out; + } + + 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; + } + + for(start = list; start[0] != '\0';) + { + + if(NULL != (comma = strchr(start, ','))) + { + comma[0] = '\0'; + } + + if(NULL != (dash = strchr(start, '-'))) + { + dash[0] = '\0'; + if(sscanf(dash + 1, "%x", &j[8]) != 1) + { + goto next; + } + } + + if(FAIL == expand_ipv6(start, buffer, sizeof(buffer))) + { + 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; + } + + if(dash == NULL) + { + 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]) + { + ret = SUCCEED; + break; + } +next: + if(dash != NULL) + { + dash[0] = '-'; + dash = NULL; + } + + if(comma != NULL) + { + comma[0] = ','; + start = comma + 1; + comma = NULL; + } + else + { + break; + } + } +out: + if(dash != NULL) + { + dash[0] = '-'; + } + + if(comma != NULL) + { + comma[0] = ','; + } + + zabbix_log(LOG_LEVEL_DEBUG, "End ip_in_list(ret:%s)", ret == SUCCEED ? "SUCCEED" : "FAIL"); + return ret; +} +#endif /*HAVE_IPV6*/ /****************************************************************************** * * * Function: ip_in_list * @@ -240,7 +437,6 @@ int calculate_item_nextcheck(zbx_uint64_t itemid, int item_type, int delay, char * Purpose: check if ip matches range of ip addresses * * * * Parameters: list - IPs [192.168.1.1-244,192.168.1.250] * - * value- value * * * * Return value: FAIL - out of range, SUCCEED - within the range * * * @@ -252,49 +448,63 @@ int calculate_item_nextcheck(zbx_uint64_t itemid, int item_type, int delay, char int ip_in_list(char *list, char *ip) { char c = '\0'; - int i1,i2,i3,i4,i5,j1,j2,j3,j4; + int i[4], j[5]; int ret = FAIL; - char *start = NULL, *end = NULL; - + char *start = NULL, *comma = NULL, *dash = NULL; - zabbix_log( LOG_LEVEL_DEBUG, "In ip_in_list(list:%s,ip:%s)", - list, - ip); + zabbix_log( LOG_LEVEL_DEBUG, "In ip_in_list(list:%s,ip:%s)", list, ip); - if(sscanf(ip,"%d.%d.%d.%d",&j1,&j2,&j3,&j4) != 4) - return FAIL; + if(sscanf(ip, "%d.%d.%d.%d", &i[0], &i[1], &i[2], &i[3]) != 4) + { +#if defined(HAVE_IPV6) + ret = ip_in_list_ipv6(list, ip); +#endif /*HAVE_IPV6*/ + goto out; + } for(start = list; start[0] != '\0';) { - end=strchr(start, ','); - - if(end != NULL) + if(NULL != (comma = strchr(start, ','))) { - c=end[0]; - end[0]='\0'; + comma[0] = '\0'; } - if(sscanf(start,"%d.%d.%d.%d-%d",&i1,&i2,&i3,&i4,&i5) == 5) + if(NULL != (dash = strchr(start, '-'))) { - if(i1==j1 && i2==j2 && i3==j3 && j4>=i4 && j4<=i5) + dash[0] = '\0'; + if(sscanf(dash + 1, "%d", &j[4]) != 1) { - ret = SUCCEED; - break; + goto next; } } - else if(sscanf(start,"%d.%d.%d.%d",&i1,&i2,&i3,&i4) == 4) + + if(sscanf(start, "%d.%d.%d.%d", &j[0], &j[1], &j[2], &j[3]) != 4) { - if(i1==j1 && i2==j2 && i3==j3 && j4==i4) - { - ret = SUCCEED; - break; - } + goto next; } - if(end != NULL) + if(dash == NULL) { - end[0]=c; - start=end+1; + j[4] = j[3]; + } + + if(i[0] == j[0] && i[1] == j[1] && i[2] == j[2] && i[3] >= j[3] && i[3] <= j[4]) + { + ret = SUCCEED; + break; + } +next: + if(dash != NULL) + { + dash[0] = '-'; + dash = NULL; + } + + if(comma != NULL) + { + comma[0] = ','; + start = comma + 1; + comma = NULL; } else { @@ -302,13 +512,18 @@ int ip_in_list(char *list, char *ip) } } - if(end != NULL) +out: + if(dash != NULL) { - end[0]=c; + dash[0] = '-'; } - zabbix_log( LOG_LEVEL_DEBUG, "End ip_in_list(ret:%s)", ret == SUCCEED?"SUCCEED":"FAIL"); + if(comma != NULL) + { + comma[0] = ','; + } + zabbix_log( LOG_LEVEL_DEBUG, "End ip_in_list(ret:%s)", ret == SUCCEED ? "SUCCEED" : "FAIL"); return ret; } diff --git a/src/libs/zbxcomms/comms.c b/src/libs/zbxcomms/comms.c index e1f9f075..534fe010 100644 --- a/src/libs/zbxcomms/comms.c +++ b/src/libs/zbxcomms/comms.c @@ -112,28 +112,59 @@ static void __zbx_zbx_set_tcp_strerror(const char *fmt, ...) * * * Parameters: * * * - * Return value: hostent or NULL - an error occured * + * Return value: * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ -struct hostent *zbx_gethost_by_ip(const char *ip) + +#if defined(HAVE_IPV6) +void zbx_gethost_by_ip(const char *ip, char *host, size_t hostlen) +{ + struct addrinfo hints, *ai = NULL; + + assert(ip); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + if(0 != getaddrinfo(ip, NULL, &hints, &ai)) + { + host[0] = '\0'; + goto out; + } + if(0 != getnameinfo(ai->ai_addr, ai->ai_addrlen, host, hostlen, NULL, 0, NI_NAMEREQD)) + { + host[0] = '\0'; + goto out; + } +out: + freeaddrinfo(ai); +} +#else +void zbx_gethost_by_ip(const char *ip, char *host, size_t hostlen) { struct in_addr addr; - struct hostent* host; + struct hostent *hst; assert(ip); - if(inet_aton(ip, &addr) != 0) + if(inet_aton(ip, &addr) == 0) { - host = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET); - if(host) return host; + host[0] = '\0'; + return; } - return (struct hostent*) NULL; + if(NULL == (hst = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET))) + { + host[0] = '\0'; + return; + } + + zbx_strlcpy(host, hst->h_name, hostlen); } +#endif /*HAVE_IPV6*/ #endif /* WINDOWS */ /****************************************************************************** @@ -232,7 +263,7 @@ static int zbx_tcp_start(void) * * * Parameters: * * * - * Return value: * + * Return value: * * * * Author: Alexei Vladishev * * * @@ -254,7 +285,7 @@ static void zbx_tcp_clean(zbx_sock_t *s) * * * Parameters: * * * - * Return value: * + * Return value: * * * * Author: Eugene Grigorjev * * * @@ -275,7 +306,7 @@ void zbx_tcp_init(zbx_sock_t *s, ZBX_SOCKET o) * * * Parameters: * * * - * Return value: sockfd - open socket * + * Return value: sockfd - open socket * * FAIL - an error occured * * * * Author: Alexei Vladishev * @@ -283,9 +314,48 @@ void zbx_tcp_init(zbx_sock_t *s, ZBX_SOCKET o) * Comments: * * * ******************************************************************************/ -int zbx_tcp_connect(zbx_sock_t *s, const char *ip, unsigned short port) +#if defined(HAVE_IPV6) +int zbx_tcp_connect(zbx_sock_t *s, const char *ip, unsigned short port) +{ + int ret=SUCCEED; + struct addrinfo *ai, hints; + 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_flags = AI_ADDRCONFIG; + hints.ai_socktype = SOCK_STREAM; + + if( 0 != getaddrinfo (ip, service, &hints, &ai)) { + zbx_set_tcp_strerror("Cannot resolve [%s]", ip); + ret=FAIL; + 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())); + ret=FAIL; + goto out; + } + + 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); + ret=FAIL; + goto out; + } +out: + freeaddrinfo (ai); + return ret; +} +#else +int zbx_tcp_connect(zbx_sock_t *s, const char *ip, unsigned short port) { - ZBX_SOCKADDR myaddr_in; ZBX_SOCKADDR servaddr_in; struct hostent *hp; @@ -299,7 +369,6 @@ int zbx_tcp_connect(zbx_sock_t *s, const char *ip, unsigned short port) zbx_set_tcp_strerror("Cannot resolve [%s]", ip); return FAIL; } - servaddr_in.sin_family = AF_INET; servaddr_in.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr; servaddr_in.sin_port = htons(port); @@ -310,10 +379,6 @@ int zbx_tcp_connect(zbx_sock_t *s, const char *ip, unsigned short port) return FAIL; } - myaddr_in.sin_family = AF_INET; - myaddr_in.sin_port = 0; - myaddr_in.sin_addr.s_addr = INADDR_ANY; - if( ZBX_TCP_ERROR == connect(s->socket,(struct sockaddr *)&servaddr_in,sizeof(ZBX_SOCKADDR)) ) { zbx_set_tcp_strerror("Cannot connect to [%s:%d] [%s]", ip, port, strerror_from_system(zbx_sock_last_error())); @@ -323,7 +388,7 @@ int zbx_tcp_connect(zbx_sock_t *s, const char *ip, unsigned short port) return SUCCEED; } - +#endif /*HAVE_IPV6*/ /****************************************************************************** * * * Function: zbx_tcp_send * @@ -332,7 +397,7 @@ int zbx_tcp_connect(zbx_sock_t *s, const char *ip, unsigned short port) * * * Parameters: * * * - * Return value: SUCCEED - success * + * Return value: SUCCEED - success * * FAIL - an error occured * * * * Author: Eugene Grigorjev * @@ -420,7 +485,7 @@ void zbx_tcp_close(zbx_sock_t *s) * * * Parameters: * * * - * Return value: SUCCEED - success * + * Return value: SUCCEED - success * * FAIL - an error occured * * * * Author: Alexei Vladishev * @@ -434,17 +499,35 @@ int zbx_tcp_listen( unsigned short listen_port ) { - ZBX_SOCKADDR serv_addr; - int on; +#if defined(HAVE_IPV6) + struct addrinfo hints, *ai = NULL; + char port[MAX_STRING_LEN]; +#else + ZBX_SOCKADDR serv_addr; +#endif /*HAVE_IPV6*/ + int on, res = FAIL, e; ZBX_TCP_START(); zbx_tcp_clean(s); - if( ZBX_SOCK_ERROR == (s->socket = socket(AF_INET,SOCK_STREAM,0)) ) +#if defined(HAVE_IPV6) + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + 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 create socket [%s:%u] [%s]", listen_ip, listen_port ,strerror_from_system(zbx_sock_last_error())); - return FAIL; + zbx_set_tcp_strerror("Cannot getaddrinfo [%s:%u] [%s]", listen_ip, listen_port, gai_strerror(e)); + goto out; + } + if(ZBX_SOCK_ERROR == (s->socket = socket(ai->ai_family, ai->ai_socktype,0))) +#else + if(ZBX_SOCK_ERROR == (s->socket = socket(AF_INET,SOCK_STREAM,0))) +#endif /*HAVE_IPV6*/ + { + zbx_set_tcp_strerror("Cannot create socket [%s:%u] [%s]", listen_ip, listen_port, strerror_from_system(zbx_sock_last_error())); + goto out; } /* Enable address reuse */ @@ -457,29 +540,38 @@ int zbx_tcp_listen( } /* Create socket Fill in local address structure */ +#if defined(HAVE_IPV6) + if( -1 == bind(s->socket, ai->ai_addr, ai->ai_addrlen)) +#else memset(&serv_addr, 0, sizeof(ZBX_SOCKADDR)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = listen_ip ? inet_addr(listen_ip) : htonl(INADDR_ANY); - serv_addr.sin_port = htons((unsigned short)listen_port); + serv_addr.sin_port = htons((unsigned short)listen_port); /* Bind socket */ if (ZBX_SOCK_ERROR == bind(s->socket,(struct sockaddr *)&serv_addr,sizeof(ZBX_SOCKADDR)) ) +#endif /*HAVE_IPV6*/ { zbx_set_tcp_strerror("Cannot bind to port %u for server %s. Error [%s]. Another zabbix_agentd already running ?", listen_port, listen_ip ? listen_ip : "[ANY]", strerror_from_system(zbx_sock_last_error())); - return FAIL; + goto out; } if( ZBX_SOCK_ERROR == listen(s->socket, SOMAXCONN) ) { zbx_set_tcp_strerror("Listen failed. [%s]", strerror_from_system(zbx_sock_last_error())); - return FAIL; + goto out; } - return SUCCEED; + res = SUCCEED; +out: +#if defined(HAVE_IPV6) + freeaddrinfo (ai); +#endif /*HAVE_IPV6*/ + return res; } /****************************************************************************** @@ -578,7 +670,7 @@ void zbx_tcp_free(zbx_sock_t *s) * * * Parameters: * * * - * Return value: SUCCEED - success * + * Return value: SUCCEED - success * * FAIL - an error occured * * * * Author: Eugene Grigorjev * @@ -722,16 +814,21 @@ int zbx_tcp_check_security( int allow_if_empty ) { - ZBX_SOCKADDR name; +#if defined(HAVE_IPV6) + struct sockaddr_storage name; + struct addrinfo hints, *ai = NULL; +#else + ZBX_SOCKADDR name; + struct hostent *hp; + char *sip; +#endif socklen_t nlen; - struct hostent *hp; - - char - tmp[MAX_STRING_LEN], + char tmp[MAX_STRING_LEN], sname[MAX_STRING_LEN], - *sip, - *host; + *start = NULL, + *end = NULL, + c = '\0'; zabbix_log( LOG_LEVEL_DEBUG, "In check_security()"); @@ -739,7 +836,11 @@ int zbx_tcp_check_security( { return SUCCEED; } +#if defined(HAVE_IPV6) + nlen = sizeof(struct sockaddr_storage); +#else nlen = sizeof(ZBX_SOCKADDR); +#endif /*HAVE_IPV6*/ if( ZBX_TCP_ERROR == getpeername(s->socket, (struct sockaddr*)&name, &nlen)) { zbx_set_tcp_strerror("Connection rejected. Getpeername failed [%s]", strerror_from_system(zbx_sock_last_error())); @@ -747,27 +848,86 @@ int zbx_tcp_check_security( } else { +#if !defined(HAVE_IPV6) strcpy(sname, inet_ntoa(name.sin_addr)); - +#endif /*HAVE_IPV6*/ strscpy(tmp,ip_list); - host = (char *)strtok(tmp,","); - - while( NULL != host ) + for(start = tmp; start[0] != '\0';) { + end = strchr(start, ','); + + if(end != NULL) + { + c = end[0]; + end[0] = '\0'; + } + /* Allow IP addresses or DNS names for authorization */ - if( 0 != (hp = zbx_gethost(host))) +#if defined(HAVE_IPV6) + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + if(0 == getaddrinfo(start, NULL, &hints, &ai)) + { + if(ai->ai_family == name.ss_family) + { + switch(ai->ai_family) + { + case AF_INET : + if(((struct sockaddr_in*)&name)->sin_addr.s_addr == ((struct sockaddr_in*)ai->ai_addr)->sin_addr.s_addr) + { + freeaddrinfo(ai); + return SUCCEED; + } + case AF_INET6 : + if(0 == memcmp(((struct sockaddr_in6*)&name)->sin6_addr.s6_addr, + ((struct sockaddr_in6*)ai->ai_addr)->sin6_addr.s6_addr, + sizeof(struct in6_addr))) + { + freeaddrinfo(ai); + return SUCCEED; + } + } + } + } + freeaddrinfo(ai); +#else + if( 0 != (hp = zbx_gethost(start))) { sip = inet_ntoa(*((struct in_addr *)hp->h_addr)); if( 0 == strcmp(sname, sip)) { - return SUCCEED; + return SUCCEED; } } - host = (char *)strtok(NULL,","); +#endif /*HAVE_IPV6*/ + if(end != NULL) + { + end[0] = c; + start = end + 1; + } + else + { + break; + } } + + if(end != NULL) + { + end[0] = c; + } + } +#if defined(HAVE_IPV6) + if(0 == getnameinfo((struct sockaddr*)&name, sizeof(name), sname, sizeof(sname), NULL, 0, NI_NUMERICHOST)) + { + zbx_set_tcp_strerror("Connection from [%s] rejected. Allowed server is [%s] ",sname, ip_list); } + else + { + zbx_set_tcp_strerror("Connection rejected. Allowed server is [%s] ", ip_list); + } +#else zbx_set_tcp_strerror("Connection from [%s] rejected. Allowed server is [%s] ",sname, ip_list); +#endif /*HAVE_IPV6*/ return FAIL; } - diff --git a/src/libs/zbxemail/email.c b/src/libs/zbxemail/email.c index b89b9cac..f507ea1b 100644 --- a/src/libs/zbxemail/email.c +++ b/src/libs/zbxemail/email.c @@ -46,111 +46,81 @@ */ int send_email(char *smtp_server,char *smtp_helo,char *smtp_email,char *mailto,char *mailsubject,char *mailbody, char *error, int max_error_len) { - int s; - int i,e; - char c[MAX_STRING_LEN], *cp = NULL; - struct hostent *hp; + int ret=SUCCEED; + zbx_sock_t s; + int i,e; + char c[MAX_STRING_LEN], *cp = NULL; - char str_time[MAX_STRING_LEN]; - struct tm *local_time = NULL; - time_t email_time; + char str_time[MAX_STRING_LEN]; + struct tm *local_time = NULL; + time_t email_time; - struct sockaddr_in myaddr_in; - struct sockaddr_in servaddr_in; + char *OK_220="220"; + char *OK_250="250"; + char *OK_251="251"; + char *OK_354="354"; - char *OK_220="220"; - char *OK_250="250"; - char *OK_251="251"; - char *OK_354="354"; + zabbix_log( LOG_LEVEL_DEBUG, "In send_email[smtp_server:%s]", smtp_server); - zabbix_log( LOG_LEVEL_DEBUG, "In send_email[smtp_server:%s]", - smtp_server); - - servaddr_in.sin_family=AF_INET; - - if(NULL == (hp = zbx_gethost(smtp_server))) - { - zbx_snprintf(error,max_error_len,"Cannot get IP for mailserver [%s]",smtp_server); - zabbix_log(LOG_LEVEL_DEBUG, "%s",error); - zabbix_syslog("%s",error); - return FAIL; - } - - servaddr_in.sin_addr.s_addr=((struct in_addr *)(hp->h_addr))->s_addr; - servaddr_in.sin_port=htons(25); - - s=socket(AF_INET,SOCK_STREAM,0); - if(s == -1) - { - zbx_snprintf(error,max_error_len,"Cannot create socket [%s]",strerror(errno)); - zabbix_log(LOG_LEVEL_DEBUG, "%s", error); - zabbix_syslog("%s", error); - return FAIL; - } - - myaddr_in.sin_family = AF_INET; - myaddr_in.sin_port=0; - myaddr_in.sin_addr.s_addr=INADDR_ANY; - - if( connect(s,(struct sockaddr *)&servaddr_in,sizeof(struct sockaddr_in)) == -1 ) + if(FAIL == zbx_tcp_connect(&s, smtp_server, 25)) { - zbx_snprintf(error,max_error_len,"Cannot connect to SMTP server [%s] [%s]", smtp_server, strerror(errno)); + zbx_snprintf(error,max_error_len,"Cannot connect to SMTP server [%s] [%s]", smtp_server, zbx_tcp_strerror()); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s",error); - close(s); - return FAIL; + ret=FAIL; + goto out; } memset(c,0,MAX_STRING_LEN); - i=read(s,c,MAX_STRING_LEN); + i=read(s.socket,c,MAX_STRING_LEN); if(i == -1) { zbx_snprintf(error,max_error_len,"Error receiving initial string from SMTP server [%s]", strerror(errno)); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s", error); - close(s); - return FAIL; + ret=FAIL; + goto out; } if(strncmp(OK_220,c,strlen(OK_220)) != 0) { zbx_snprintf(error,max_error_len,"No welcome message 220* from SMTP server [%s]", c); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s", error); - close(s); - return FAIL; + ret=FAIL; + goto out; } if(strlen(smtp_helo) != 0) { memset(c,0,MAX_STRING_LEN); zbx_snprintf(c,sizeof(c),"HELO %s\r\n",smtp_helo); - e=write(s,c,strlen(c)); + e=write(s.socket,c,strlen(c)); if(e == -1) { zbx_snprintf(error,max_error_len,"Error sending HELO to mailserver [%s]", strerror(errno)); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s", error); - close(s); - return FAIL; + ret=FAIL; + goto out; } memset(c,0,MAX_STRING_LEN); - i=read(s,c,MAX_STRING_LEN); + i=read(s.socket,c,MAX_STRING_LEN); if(i == -1) { zbx_snprintf(error,max_error_len,"Error receiving answer on HELO request [%s]", strerror(errno)); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s", error); - close(s); - return FAIL; + ret=FAIL; + goto out; } if(strncmp(OK_250,c,strlen(OK_250)) != 0) { zbx_snprintf(error,max_error_len,"Wrong answer on HELO [%s]", c); zabbix_log(LOG_LEVEL_DEBUG, "%s",error); zabbix_syslog("%s",error); - close(s); - return FAIL; + ret=FAIL; + goto out; } } @@ -158,55 +128,55 @@ int send_email(char *smtp_server,char *smtp_helo,char *smtp_email,char *mailto,c zbx_snprintf(c,sizeof(c),"MAIL FROM: <%s>\r\n",smtp_email); - e=write(s,c,strlen(c)); + e=write(s.socket,c,strlen(c)); if(e == -1) { zbx_snprintf(error,max_error_len,"Error sending MAIL FROM to mailserver [%s]", strerror(errno)); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s", error); - close(s); - return FAIL; + ret=FAIL; + goto out; } memset(c,0,MAX_STRING_LEN); - i=read(s,c,MAX_STRING_LEN); + i=read(s.socket,c,MAX_STRING_LEN); if(i == -1) { zbx_snprintf(error,max_error_len,"Error receiving answer on MAIL FROM request [%s]", strerror(errno)); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s", error); - close(s); - return FAIL; + ret=FAIL; + goto out; } if(strncmp(OK_250,c,strlen(OK_250)) != 0) { zbx_snprintf(error,max_error_len,"Wrong answer on MAIL FROM [%s]", c); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s", error); - close(s); - return FAIL; + ret=FAIL; + goto out; } memset(c,0,MAX_STRING_LEN); zbx_snprintf(c,sizeof(c),"RCPT TO: <%s>\r\n",mailto); - e=write(s,c,strlen(c)); + e=write(s.socket,c,strlen(c)); if(e == -1) { zbx_snprintf(error,max_error_len,"Error sending RCPT TO to mailserver [%s]", strerror(errno)); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s", error); - close(s); - return FAIL; + ret=FAIL; + goto out; } memset(c,0,MAX_STRING_LEN); - i=read(s,c,MAX_STRING_LEN); + i=read(s.socket,c,MAX_STRING_LEN); if(i == -1) { zbx_snprintf(error,max_error_len,"Error receiving answer on RCPT TO request [%s]", strerror(errno)); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s", error); - close(s); - return FAIL; + ret=FAIL; + goto out; } /* May return 251 as well: User not local; will forward to <forward-path>. See RFC825 */ if( strncmp(OK_250,c,strlen(OK_250)) != 0 && strncmp(OK_251,c,strlen(OK_251)) != 0) @@ -214,38 +184,38 @@ int send_email(char *smtp_server,char *smtp_helo,char *smtp_email,char *mailto,c zbx_snprintf(error,max_error_len,"Wrong answer on RCPT TO [%s]", c); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s", error); - close(s); - return FAIL; + ret=FAIL; + goto out; } memset(c,0,MAX_STRING_LEN); zbx_snprintf(c,sizeof(c),"DATA\r\n"); - e=write(s,c,strlen(c)); + e=write(s.socket,c,strlen(c)); if(e == -1) { zbx_snprintf(error,max_error_len,"Error sending DATA to mailserver [%s]", strerror(errno)); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s", error); - close(s); - return FAIL; + ret=FAIL; + goto out; } memset(c,0,MAX_STRING_LEN); - i=read(s,c,MAX_STRING_LEN); + i=read(s.socket,c,MAX_STRING_LEN); if(i == -1) { zbx_snprintf(error,max_error_len,"Error receivng answer on DATA request [%s]", strerror(errno)); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s", error); - close(s); - return FAIL; + ret=FAIL; + goto out; } if(strncmp(OK_354,c,strlen(OK_354)) != 0) { zbx_snprintf(error,max_error_len,"Wrong answer on DATA [%s]", c); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s", error); - close(s); - return FAIL; + ret=FAIL; + goto out; } cp = string_replace(mailsubject, "\r\n", "\n"); @@ -261,7 +231,7 @@ int send_email(char *smtp_server,char *smtp_helo,char *smtp_email,char *mailto,c local_time = localtime(&email_time); strftime( str_time, MAX_STRING_LEN, "%a, %d %b %Y %H:%M:%S %z", local_time ); cp = zbx_dsprintf(cp,"From:<%s>\r\nTo:<%s>\r\nDate: %s\r\nSubject: %s\r\n\r\n%s",smtp_email,mailto,str_time,mailsubject, mailbody); - e=write(s,cp,strlen(cp)); + e=write(s.socket,cp,strlen(cp)); zbx_free(cp); zbx_free(mailsubject); zbx_free(mailbody); @@ -270,54 +240,52 @@ int send_email(char *smtp_server,char *smtp_helo,char *smtp_email,char *mailto,c zbx_snprintf(error,max_error_len,"Error sending mail subject and body to mailserver [%s]", strerror(errno)); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s", error); - close(s); - return FAIL; + ret=FAIL; + goto out; } memset(c,0,MAX_STRING_LEN); zbx_snprintf(c,sizeof(c),"\r\n.\r\n"); - e=write(s,c,strlen(c)); + e=write(s.socket,c,strlen(c)); if(e == -1) { zbx_snprintf(error,max_error_len,"Error sending . to mailserver [%s]", strerror(errno)); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s",error); - close(s); - return FAIL; + ret=FAIL; + goto out; } memset(c,0,MAX_STRING_LEN); - i=read(s,c,MAX_STRING_LEN); + i=read(s.socket,c,MAX_STRING_LEN); if(i == -1) { - zabbix_log(LOG_LEVEL_DEBUG, "Error receivng answer on . request [%s]", strerror(errno)); - zabbix_syslog("Error receivng answer on . request [%s]", strerror(errno)); zbx_snprintf(error,max_error_len,"Error receivng answer on . request [%s]", strerror(errno)); - close(s); - return FAIL; + zabbix_log(LOG_LEVEL_DEBUG, "%s", error); + zabbix_syslog("%s", error); + ret=FAIL; + goto out; } if(strncmp(OK_250,c,strlen(OK_250)) != 0) { zbx_snprintf(error,max_error_len,"Wrong answer on end of data [%s]", c); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s",error); - close(s); - return FAIL; + ret=FAIL; + goto out; } memset(c,0,MAX_STRING_LEN); zbx_snprintf(c,sizeof(c),"QUIT\r\n"); - e=write(s,c,strlen(c)); + e=write(s.socket,c,strlen(c)); if(e == -1) { zbx_snprintf(error,max_error_len,"Error sending QUIT to mailserver [%s]", strerror(errno)); zabbix_log(LOG_LEVEL_DEBUG, "%s", error); zabbix_syslog("%s",error); - close(s); - return FAIL; + ret=FAIL; + goto out; } - - close(s); - - - return SUCCEED; +out: + zbx_tcp_close(&s); + return ret; } diff --git a/src/zabbix_server/discoverer/discoverer.c b/src/zabbix_server/discoverer/discoverer.c index bbbe876b..52e5ad36 100644 --- a/src/zabbix_server/discoverer/discoverer.c +++ b/src/zabbix_server/discoverer/discoverer.c @@ -710,12 +710,13 @@ static void process_rule(DB_DRULE *rule) DB_ROW row; DB_DCHECK check; - char ip[MAX_STRING_LEN]; - int i1,i2,i3,i4,i5; - int first, last, i; + char ip[MAX_STRING_LEN], prefix[MAX_STRING_LEN]; + unsigned int j[9], i; + int first, last, ipv6; char *curr_range = NULL, - *next_range = NULL; + *next_range = NULL, + *dash = NULL, *colon; assert(rule); @@ -725,26 +726,78 @@ static void process_rule(DB_DRULE *rule) for ( curr_range = rule->iprange; curr_range; curr_range = next_range ) { /* split by ',' */ - if ( (next_range = strchr(curr_range, ',')) ) + if ( NULL != (next_range = strchr(curr_range, ',')) ) { - *next_range = '\0'; + next_range[0] = '\0'; + } + + if ( NULL != (dash = strchr(curr_range, '-')) ) + { + dash[0] = '\0'; } first = last = -1; - if ( sscanf(curr_range, "%d.%d.%d.%d-%d", &i1, &i2, &i3, &i4, &i5) == 5 ) +#if defined(HAVE_IPV6) + if ( SUCCEED == expand_ipv6(curr_range, ip, sizeof(ip)) ) { - first = i4; - last = i5; + ipv6 = 1; + if( sscanf(ip, "%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 ) + { + first = j[7]; + + zbx_strlcpy( prefix, curr_range, sizeof(prefix) ); + if( NULL != (colon = strrchr(prefix, ':')) ) + { + ( colon + 1 )[0] = '\0'; + } + } + + if( dash != NULL ) + { + if( sscanf(dash + 1, "%x", &j[8]) == 1 ) + { + last = j[8]; + } + } + else + { + last = first; + } } - else if( sscanf(curr_range, "%d.%d.%d.%d", &i1, &i2, &i3, &i4) == 4 ) + else { - first = last = i4; +#endif /* HAVE_IPV6 */ + ipv6 = 0; + if( sscanf(curr_range, "%d.%d.%d.%d", &j[0], &j[1], &j[2], &j[3]) == 4 ) + { + first = j[3]; + } + + if( dash != NULL ) + { + if( sscanf(dash + 1, "%d", &j[4]) == 1 ) + { + last = j[4]; + } + } + else + { + last = first; + } +#if defined(HAVE_IPV6) + } +#endif /* HAVE_IPV6 */ + + if( dash ) + { + dash[0] = '-'; + dash = NULL; } if ( next_range ) { - *next_range = ','; - next_range++; + next_range[0] = ','; + next_range ++; } if( first < 0 || last < 0 ) @@ -756,9 +809,13 @@ static void process_rule(DB_DRULE *rule) for ( i = first; i <= last; i++ ) { - zbx_snprintf(ip, sizeof(ip), "%d.%d.%d.%d", i1, i2, i3, i); + switch( ipv6 ) + { + case 0 : zbx_snprintf(ip, sizeof(ip), "%d.%d.%d.%d", j[0], j[1], j[2], i); break; + case 1 : zbx_snprintf(ip, sizeof(ip), "%s%x", prefix, i); break; + } - zabbix_log(LOG_LEVEL_DEBUG, "IP [%s]", ip); + zabbix_log(LOG_LEVEL_DEBUG, "Discovery: process_rule() [first %d] [last %d] [IP %s]", prefix, first, last, ip); result = DBselect("select dcheckid,druleid,type,key_,snmp_community,ports from dchecks where druleid=" ZBX_FS_UI64, rule->druleid); diff --git a/src/zabbix_server/operations.c b/src/zabbix_server/operations.c index c45d65a4..c90c57ba 100644 --- a/src/zabbix_server/operations.c +++ b/src/zabbix_server/operations.c @@ -461,8 +461,7 @@ static zbx_uint64_t add_discovered_host(zbx_uint64_t dhostid) DB_ROW row2; zbx_uint64_t hostid = 0; char *ip; - struct hostent* host; - char host_esc[MAX_STRING_LEN]; + char host[MAXDNAME], host_esc[MAX_STRING_LEN]; zabbix_log(LOG_LEVEL_DEBUG, "In add_discovered_host(dhostid:" ZBX_FS_UI64 ")", dhostid); @@ -475,17 +474,10 @@ static zbx_uint64_t add_discovered_host(zbx_uint64_t dhostid) ip=row[0]; alarm(CONFIG_TIMEOUT); - host = zbx_gethost_by_ip(ip); + zbx_gethost_by_ip(ip, host, sizeof(host)); alarm(0); - if(host != NULL) - { - DBescape_string(host->h_name, host_esc, sizeof(host_esc)); - } - else - { - host_esc[0]='\0'; - } + DBescape_string(host, host_esc, sizeof(host_esc)); result2 = DBselect("select hostid from hosts where ip='%s' and " ZBX_COND_NODEID, ip, @@ -494,23 +486,11 @@ static zbx_uint64_t add_discovered_host(zbx_uint64_t dhostid) if(!row2 || DBis_null(row2[0]) == SUCCEED) { hostid = DBget_maxid("hosts","hostid"); - /* Use host name if exists, IP otherwise */ - if(host_esc[0] != '\0') - { - DBexecute("insert into hosts (hostid,host,useip,ip,dns) values (" ZBX_FS_UI64 ",'%s',1,'%s','%s')", - hostid, - host_esc, - ip, - host_esc); - } - else - { - DBexecute("insert into hosts (hostid,host,useip,ip,dns) values (" ZBX_FS_UI64 ",'%s',1,'%s','%s')", - hostid, - ip, - ip, - host_esc); - } + DBexecute("insert into hosts (hostid,host,useip,ip,dns) values (" ZBX_FS_UI64 ",'%s',1,'%s','%s')", + hostid, + (host[0] != '\0' ? host_esc : ip), /* Use host name if exists, IP otherwise */ + ip, + host_esc); } else { diff --git a/src/zabbix_server/server.c b/src/zabbix_server/server.c index ccbf9ecd..cf3f3150 100644 --- a/src/zabbix_server/server.c +++ b/src/zabbix_server/server.c @@ -16,9 +16,9 @@ ** along with this program; if not, write to the Free Software ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. **/ - -/*#define ZABBIX_TEST*/ - +/* +#define ZABBIX_TEST +*/ #include "common.h" #include "cfg.h" @@ -498,14 +498,13 @@ void test_variable_argument_list(void) void test_zbx_gethost(void) { - struct hostent* host; +/* struct hostent* host; char hostname[]="194.8.11.69"; -/* char hostname[]="gobbo.caves.lv";*/ host = zbx_gethost_by_ip(hostname); - printf("Host1 [%s]\n", host->h_name); + printf("Host1 [%s]\n", host->h_name);*/ } void test_templates() @@ -564,16 +563,17 @@ ZBX_TEST_TIME expressions[]= printf("Passed OK\n"); } */ -/* + void test_email() { - char str_error[0xFF]; + char str_error[MAX_STRING_LEN]; + alarm(5); if ( FAIL == send_email( - "test.com", - "test.com", - "test@test.com", - "test@test.com", + "mail.apollo.lv", + "zabbix.com", + "sasha@zabbix.com", + "aleksander.vladishev@zabbix.com", "This is a TEST message", "Big message\r\n" " 1 Line\n" @@ -601,10 +601,10 @@ void test_email() printf("ERROR: %s\n", str_error); else printf("OK\n"); - + alarm(0); } -*/ + /* void test_extract_numbers(void) @@ -649,6 +649,66 @@ void test_trigger_description() } */ +void test_zbx_tcp_connect(void) +{ +#define ZBX_TEST_TCP_CONNECT struct zbx_test_tcp_connect_t +ZBX_TEST_TCP_CONNECT +{ + char *hostname; + unsigned short port; +}; + +ZBX_TEST_TCP_CONNECT expressions[]= +{ + {"127.0.0.1", 80}, + {"support.zabbix.com", 8080},/*81.198.122.245*/ + {"www.iscentrs.lv", 80},/*81.198.60.94*/ + {"81.171.84.52", 80}, + {"64.233.183.103", 80},/*nf-in-f103.google.com*/ + {"::1", 80}, + {"::1", 22}, + {"12fc::5", 80}, + {"192.168.3.5", 80}, + {NULL} +}; + + int i; + zbx_sock_t s; + char host[MAXDNAME]; + char ip_list[] = "81.171.84.52,nf-in-f103.google.com,ip6-localhost,localhost"; + + for(i = 0; expressions[i].hostname != NULL; i ++) + { + zbx_gethost_by_ip(expressions[i].hostname, host, sizeof(host)); + printf("[%25s]:%-5d %-30s ", expressions[i].hostname, expressions[i].port, host); + + alarm(5); + switch(zbx_tcp_connect(&s, expressions[i].hostname, expressions[i].port)) + { + case SUCCEED : + printf("Succeed"); + + if(FAIL == zbx_tcp_check_security(&s, ip_list, 0)) + { + printf(" \n%s", zbx_tcp_strerror()); + } + zbx_tcp_close(&s); + break; + case FAIL : + printf("Fail %s\n", zbx_tcp_strerror()); + break; + } + alarm(0); + printf("\n"); + } +} +/* +static void test_child_signal_handler(int sig) +{ + printf( "sdfsdfsdfsf" ); +} +*/ + void test_ip_in_list() { #define ZBX_TEST_IP struct zbx_test_ip_t @@ -661,12 +721,21 @@ ZBX_TEST_IP ZBX_TEST_IP expressions[]= { - {"10.0.0.1-255", "10.0.0.30", SUCCEED}, + {"10.0.0.1-29", "10.0.0.30", FAIL}, {"192.168.0.1-255,192.168.1.1-255", "192.168.2.201", FAIL}, - {"172.16.0.0,172.16.0.1,172.16.0.2-200,172.16.0.201", "172.16.0.201", SUCCEED}, - {"172.31.255.1-255", "172.31.255.43", SUCCEED}, + {"172.16.0.0,172.16.0.1,172.16.0.2,172.16.0.44-250", "172.16.0.201", SUCCEED}, + {"172.31.255.43-55", "172.31.255.47", SUCCEED}, {"86.57.15.94", "86.57.15.95", FAIL}, {"86.57.15.94", "86.57.15.94", SUCCEED}, +#if defined(HAVE_IPV6) + {"2312:333::32-64,12fc::1-fffc", "12fc::ffff", FAIL}, + {"2312:333::32-64,12fc::1-fffc", "2312:333::44", SUCCEED}, + {"::a:b:a,::a:b:b,::a:b:c-e", "::a:b:f", FAIL}, + {"192.168.200.1,::a:b:a,::a:b:b,::a:b:c-e,10.0.0.2", "::a:b:d", SUCCEED}, + {"192.168.200.1,::a:b:a,::a:b:b,::a:b:c-e,10.0.0.2", "10.0.0.2", SUCCEED}, + {"192.168.200.1,::a:b:a,::a:b:b,::a:b:c-,10.0.0.2", "::a:b:d", FAIL}, + {"a:b:c::-f", "a:b:c::3", SUCCEED}, +#endif /*HAVE_IPV6*/ {NULL} }; int i; @@ -680,11 +749,11 @@ ZBX_TEST_IP expressions[]= strcpy(list, expressions[i].list); result = ip_in_list(list, expressions[i].ip); - printf("list [%s] ip [%s] expected [%d] got [%d]\n", + printf("list [%50s] ip [%20s] expected [%7s] got [%7s]\n", expressions[i].list, expressions[i].ip, - expressions[i].result, - result); + expressions[i].result == SUCCEED ? "SUCCEED" : "FAIL", + result == SUCCEED ? "SUCCEED" : "FAIL"); if(expressions[i].result!=result) { printf("FAILED!\n"); @@ -721,6 +790,7 @@ void test() /* test_email(); */ /* test_extract_numbers(); */ /* test_trigger_description(); */ +/* test_zbx_tcp_connect( );*/ test_ip_in_list(); printf("\n-= Test completed =-\n"); @@ -802,6 +872,18 @@ int main(int argc, char **argv) } #ifdef ZABBIX_TEST +/* struct sigaction phan; + + phan.sa_handler = test_child_signal_handler; + sigemptyset(&phan.sa_mask); + phan.sa_flags = 0; + + sigaction(SIGINT, &phan, NULL); + sigaction(SIGQUIT, &phan, NULL); + sigaction(SIGTERM, &phan, NULL); + sigaction(SIGPIPE, &phan, NULL); + sigaction(SIGCHLD, &phan, NULL); +*/ test(); zbx_on_exit(); @@ -852,6 +934,11 @@ int MAIN_ZABBIX_ENTRY(void) #else # define ODBC_FEATURE_STATUS " NO" #endif +#ifdef HAVE_IPV6 +# define IPV6_FEATURE_STATUS "YES" +#else +# define IPV6_FEATURE_STATUS " NO" +#endif /* zabbix_log( LOG_LEVEL_WARNING, "INFO [%s]", ZBX_SQL_MOD(a,%d)); */ zabbix_log( LOG_LEVEL_WARNING, "Starting zabbix_server. ZABBIX %s.", ZABBIX_VERSION); @@ -861,6 +948,7 @@ int MAIN_ZABBIX_ENTRY(void) zabbix_log( LOG_LEVEL_WARNING, "WEB monitoring: " LIBCURL_FEATURE_STATUS ); zabbix_log( LOG_LEVEL_WARNING, "Jabber notifications: " JABBER_FEATURE_STATUS ); zabbix_log( LOG_LEVEL_WARNING, "ODBC: " ODBC_FEATURE_STATUS ); + zabbix_log( LOG_LEVEL_WARNING, "IPv6 support: " IPV6_FEATURE_STATUS ); zabbix_log( LOG_LEVEL_WARNING, "**************************"); DBconnect(ZBX_DB_CONNECT_EXIT); |