115
* Return value: hostent or NULL - an error occured *
117
117
* Author: Alexei Vladishev *
121
121
******************************************************************************/
122
struct hostent *zbx_gethost_by_ip(const char *ip)
123
#if defined(HAVE_IPV6)
124
void zbx_gethost_by_ip(const char *ip, char *host, size_t hostlen)
126
struct addrinfo hints, *ai = NULL;
130
memset(&hints, 0, sizeof(hints));
131
hints.ai_family = PF_UNSPEC;
132
if(0 != getaddrinfo(ip, NULL, &hints, &ai))
137
if(0 != getnameinfo(ai->ai_addr, ai->ai_addrlen, host, hostlen, NULL, 0, NI_NAMEREQD))
147
void zbx_gethost_by_ip(const char *ip, char *host, size_t hostlen)
124
149
struct in_addr addr;
125
struct hostent* host;
129
if(inet_aton(ip, &addr) != 0)
131
host = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
132
if(host) return host;
135
return (struct hostent*) NULL;
154
if(inet_aton(ip, &addr) == 0)
160
if(NULL == (hst = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET)))
166
zbx_strlcpy(host, hst->h_name, hostlen);
169
#endif /* _WINDOWS */
139
171
/******************************************************************************
285
317
******************************************************************************/
286
int zbx_tcp_connect(zbx_sock_t *s, const char *ip, unsigned short port)
288
ZBX_SOCKADDR myaddr_in;
318
#if defined(HAVE_IPV6)
319
int zbx_tcp_connect(zbx_sock_t *s,
326
struct addrinfo *ai = NULL, hints;
327
char service[MAX_STRING_LEN];
333
zbx_snprintf(service, sizeof(service), "%d", port);
334
memset(&hints, 0x00, sizeof(struct addrinfo));
335
hints.ai_family = PF_UNSPEC;
336
hints.ai_socktype = SOCK_STREAM;
338
if (0 != getaddrinfo(ip, service, &hints, &ai)) {
339
zbx_set_tcp_strerror("Cannot resolve [%s]", ip);
343
if (ZBX_SOCK_ERROR == (s->socket = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol))) {
344
zbx_set_tcp_strerror("Cannot create socket [%s]:%d [%s]", ip, port ,strerror_from_system(zbx_sock_last_error()));
349
s->timeout = timeout;
350
#if defined(_WINDOWS)
352
if (setsockopt(s->socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)) == ZBX_TCP_ERROR)
353
zbx_set_tcp_strerror("setsockopt() failed with error %d: %s", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error()));
355
if (setsockopt(s->socket, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout)) == ZBX_TCP_ERROR)
356
zbx_set_tcp_strerror("setsockopt() failed with error %d: %s", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error()));
362
if (ZBX_TCP_ERROR == connect(s->socket, ai->ai_addr, ai->ai_addrlen)) {
363
zbx_set_tcp_strerror("*** Cannot connect to [%s]:%d [%s]", ip, port, strerror_from_system(zbx_sock_last_error()));
375
int zbx_tcp_connect(zbx_sock_t *s,
289
381
ZBX_SOCKADDR servaddr_in;
291
382
struct hostent *hp;
295
386
zbx_tcp_clean(s);
297
if(NULL == (hp = zbx_gethost(ip)))
388
if (NULL == (hp = zbx_gethost(ip))) {
299
389
zbx_set_tcp_strerror("Cannot resolve [%s]", ip);
304
394
servaddr_in.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
305
395
servaddr_in.sin_port = htons(port);
307
if( ZBX_SOCK_ERROR == (s->socket = socket(AF_INET,SOCK_STREAM,0)) )
397
if (ZBX_SOCK_ERROR == (s->socket = socket(AF_INET,SOCK_STREAM,0))) {
309
398
zbx_set_tcp_strerror("Cannot create socket [%s:%d] [%s]", ip, port ,strerror_from_system(zbx_sock_last_error()));
313
myaddr_in.sin_family = AF_INET;
314
myaddr_in.sin_port = 0;
315
myaddr_in.sin_addr.s_addr = INADDR_ANY;
317
if( ZBX_TCP_ERROR == connect(s->socket,(struct sockaddr *)&servaddr_in,sizeof(ZBX_SOCKADDR)) )
403
s->timeout = timeout;
404
#if defined(_WINDOWS)
406
if (setsockopt(s->socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)) == ZBX_TCP_ERROR)
407
zbx_set_tcp_strerror("setsockopt() failed with error %d: %s", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error()));
409
if (setsockopt(s->socket, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout)) == ZBX_TCP_ERROR)
410
zbx_set_tcp_strerror("setsockopt() failed with error %d: %s", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error()));
416
if (ZBX_TCP_ERROR == connect(s->socket,(struct sockaddr *)&servaddr_in,sizeof(ZBX_SOCKADDR))) {
319
417
zbx_set_tcp_strerror("Cannot connect to [%s:%d] [%s]", ip, port, strerror_from_system(zbx_sock_last_error()));
320
418
zbx_tcp_close(s);
430
532
******************************************************************************/
433
const char *listen_ip,
434
unsigned short listen_port
437
ZBX_SOCKADDR serv_addr;
444
if( ZBX_SOCK_ERROR == (s->socket = socket(AF_INET,SOCK_STREAM,0)) )
446
zbx_set_tcp_strerror("Cannot create socket [%s:%u] [%s]", listen_ip, listen_port ,strerror_from_system(zbx_sock_last_error()));
533
#if defined(HAVE_IPV6)
536
const char *listen_ip,
537
unsigned short listen_port
540
struct addrinfo hints, *ai = NULL, *current_ai;
541
char port[MAX_STRING_LEN];
542
int e, on, ret = FAIL;
548
memset(&hints, 0, sizeof(hints));
549
hints.ai_family = PF_UNSPEC;
550
hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
551
hints.ai_socktype = SOCK_STREAM;
552
zbx_snprintf(port, sizeof(port), "%d", listen_port);
553
if(0 != (e = getaddrinfo(listen_ip, port, &hints, &ai)))
555
zbx_set_tcp_strerror("Cannot resolve address [[%s]:%u], error %d: %s", listen_ip, listen_port, e, gai_strerror(e));
559
for(s->num_socks = 0, current_ai = ai; current_ai != NULL; current_ai = current_ai->ai_next)
561
if(s->num_socks == FD_SETSIZE) {
564
/* This example only supports PF_INET and PF_INET6. */
565
if((current_ai->ai_family != PF_INET) && (current_ai->ai_family != PF_INET6))
568
if((s->sockets[s->num_socks] = socket(current_ai->ai_family, current_ai->ai_socktype, current_ai->ai_protocol)) == ZBX_SOCK_ERROR) {
569
zbx_set_tcp_strerror("socket() failed with error %d: %s", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error()));
573
/* Enable address reuse */
574
/* This is to immediately use the address even if it is in TIME_WAIT state */
575
/* http://www-128.ibm.com/developerworks/linux/library/l-sockpit/index.html */
577
if(setsockopt(s->sockets[s->num_socks], SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)) == ZBX_TCP_ERROR)
579
zbx_set_tcp_strerror("setsockopt() failed with error %d: %s", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error()));
582
/* Create socket Fill in local address structure */
583
if(bind(s->sockets[s->num_socks], current_ai->ai_addr, current_ai->ai_addrlen) == ZBX_TCP_ERROR) {
584
zbx_set_tcp_strerror("bind() failed with error %d: %s", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error()));
585
zbx_sock_close(s->sockets[s->num_socks]);
589
if(ZBX_SOCK_ERROR == listen(s->sockets[s->num_socks], SOMAXCONN) )
591
zbx_set_tcp_strerror("listen() failed with error %d: %s", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error()));
592
zbx_sock_close(s->sockets[s->num_socks]);
599
if(s->num_socks == 0) {
600
zbx_set_tcp_strerror("zbx_tcp_listen() Fatal error: unable to serve on any address. [[%s]:%u]", listen_ip, listen_port);
612
const char *listen_ip,
613
unsigned short listen_port
616
ZBX_SOCKADDR serv_addr;
623
if(ZBX_SOCK_ERROR == (s->socket = socket(AF_INET,SOCK_STREAM,0)))
625
zbx_set_tcp_strerror("Cannot create socket [%s:%u] [%s]", listen_ip, listen_port, strerror_from_system(zbx_sock_last_error()));
450
629
/* Enable address reuse */
500
681
******************************************************************************/
682
#if defined(HAVE_IPV6)
683
int zbx_tcp_accept(zbx_sock_t *s)
685
struct sockaddr_storage serv_addr;
687
ZBX_SOCKET accepted_socket;
695
/* For connection orientated protocols, we will handle the
696
packets comprising a connection collectively. For datagram
697
protocols, we have to handle each datagram individually.
699
Check to see if we have any sockets remaining to be served
700
from previous time through this loop. If not, call select()
701
to wait for a connection request or a datagram to arrive. */
703
for(i = 0; i < s->num_socks; i++) {
704
#if !defined(_WINDOWS)
705
if(s->sockets[i] > n)
708
if(FD_ISSET(s->sockets[i], &sock_set))
712
if(i == s->num_socks) {
713
for (i = 0; i < s->num_socks; i++)
714
FD_SET(s->sockets[i], &sock_set);
715
if(select(n + 1, &sock_set, 0, 0, 0) == ZBX_TCP_ERROR) {
716
zbx_set_tcp_strerror("select() failed with error %d: %s", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error()));
720
for (i = 0; i < s->num_socks; i++) {
721
if (FD_ISSET(s->sockets[i], &sock_set)) {
722
FD_CLR(s->sockets[i], &sock_set);
727
/* Since this socket was returned by the select(), we know we
728
have a connection waiting and that this accept() won't block.*/
729
nlen = sizeof(serv_addr);
730
if((accepted_socket = (ZBX_SOCKET)accept(s->sockets[i], (struct sockaddr *)&serv_addr, &nlen)) == ZBX_SOCK_ERROR) {
731
zbx_set_tcp_strerror("accept() failed with error %d: %s", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error()));
735
s->socket2 = s->socket; /* remember main socket */
736
s->socket = accepted_socket; /* replace socket to accepted */
501
742
int zbx_tcp_accept(zbx_sock_t *s)
503
744
ZBX_SOCKADDR serv_addr;
504
745
ZBX_SOCKET accepted_socket;
508
nlen = sizeof(ZBX_SOCKADDR);
748
nlen = sizeof(serv_addr);
510
750
zbx_tcp_unaccept(s);
742
nlen = sizeof(ZBX_SOCKADDR);
743
if( ZBX_TCP_ERROR == getpeername(s->socket, (struct sockaddr*)&name, &nlen))
989
if( ZBX_TCP_ERROR == getpeername(s->socket, (struct sockaddr*)&name, &nlen))
745
991
zbx_set_tcp_strerror("Connection rejected. Getpeername failed [%s]", strerror_from_system(zbx_sock_last_error()));
996
#if !defined(HAVE_IPV6)
750
997
strcpy(sname, inet_ntoa(name.sin_addr));
999
if(sscanf(sname, "%d.%d.%d.%d", &i[0], &i[1], &i[2], &i[3]) != 4)
1003
#endif /*HAVE_IPV6*/
752
1004
strscpy(tmp,ip_list);
754
host = (char *)strtok(tmp,",");
756
while( NULL != host )
1006
for(start = tmp; start[0] != '\0';)
1008
end = strchr(start, ',');
758
1016
/* Allow IP addresses or DNS names for authorization */
759
if( 0 != (hp = zbx_gethost(host)))
1017
#if defined(HAVE_IPV6)
1018
memset(&hints, 0, sizeof(hints));
1019
hints.ai_family = PF_UNSPEC;
1020
if(0 == getaddrinfo(start, NULL, &hints, &ai))
1022
if(ai->ai_family == name.ss_family)
1024
switch(ai->ai_family)
1027
if(((struct sockaddr_in*)&name)->sin_addr.s_addr == ((struct sockaddr_in*)ai->ai_addr)->sin_addr.s_addr)
1033
if(0 == memcmp(((struct sockaddr_in6*)&name)->sin6_addr.s6_addr,
1034
((struct sockaddr_in6*)ai->ai_addr)->sin6_addr.s6_addr,
1035
sizeof(struct in6_addr)))
1045
if( 0 != (hp = zbx_gethost(start)))
761
1047
sip = inet_ntoa(*((struct in_addr *)hp->h_addr));
762
if( 0 == strcmp(sname, sip))
1048
if(sscanf(sip, "%d.%d.%d.%d", &j[0], &j[1], &j[2], &j[3]) == 4)
1050
if(i[0] == j[0] && i[1] == j[1] && i[2] == j[2] && i[3] == j[3])
767
host = (char *)strtok(NULL,",");
1056
#endif /*HAVE_IPV6*/
1073
#if defined(HAVE_IPV6)
1074
if(0 == getnameinfo((struct sockaddr*)&name, sizeof(name), sname, sizeof(sname), NULL, 0, NI_NUMERICHOST))
1076
zbx_set_tcp_strerror("Connection from [%s] rejected. Allowed server is [%s] ",sname, ip_list);
1080
zbx_set_tcp_strerror("Connection rejected. Allowed server is [%s] ", ip_list);
770
1083
zbx_set_tcp_strerror("Connection from [%s] rejected. Allowed server is [%s] ",sname, ip_list);
1084
#endif /*HAVE_IPV6*/