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 /src/libs | |
| parent | cb2c5743fee519c1490317552b98a09f48daf92a (diff) | |
[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
Diffstat (limited to 'src/libs')
| -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 |
3 files changed, 522 insertions, 179 deletions
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; } |
