~ubuntu-dev/ubuntu/lucid/zabbix/lucid-201002101903

« back to all changes in this revision

Viewing changes to src/libs/zbxcomms/comms.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephan Hermann
  • Date: 2008-06-04 09:22:37 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20080604092237-zgwq7kmraj1oohoz
Tags: 1:1.4.5-1ubuntu1
* Merge from debian unstable, remaining changes: 
  + fixing missing pid directory in /var/run
* Added the same patch to debian/zabbix-server-{mysql,pgsql}.zabbix-server.init
  (LP: #172775)

Show diffs side-by-side

added added

removed removed

Lines of Context:
112
112
 *                                                                            *
113
113
 * Parameters:                                                                *
114
114
 *                                                                            *
115
 
 * Return value: hostent or NULL - an error occured                           *
 
115
 * Return value:                                                              *
116
116
 *                                                                            *
117
117
 * Author: Alexei Vladishev                                                   *
118
118
 *                                                                            *
119
119
 * Comments:                                                                  *
120
120
 *                                                                            *
121
121
 ******************************************************************************/
122
 
struct hostent  *zbx_gethost_by_ip(const char *ip)
 
122
 
 
123
#if defined(HAVE_IPV6)
 
124
void    zbx_gethost_by_ip(const char *ip, char *host, size_t hostlen)
 
125
{
 
126
        struct  addrinfo hints, *ai = NULL;
 
127
        
 
128
        assert(ip);
 
129
 
 
130
        memset(&hints, 0, sizeof(hints));
 
131
        hints.ai_family = PF_UNSPEC;
 
132
        if(0 != getaddrinfo(ip, NULL, &hints, &ai))
 
133
        {
 
134
                host[0] = '\0';
 
135
                goto out;
 
136
        }
 
137
        if(0 != getnameinfo(ai->ai_addr, ai->ai_addrlen, host, hostlen, NULL, 0, NI_NAMEREQD))
 
138
        {
 
139
                host[0] = '\0';
 
140
                goto out;
 
141
        }
 
142
out:
 
143
        if (NULL != ai)
 
144
                freeaddrinfo(ai);
 
145
}
 
146
#else
 
147
void    zbx_gethost_by_ip(const char *ip, char *host, size_t hostlen)
123
148
{
124
149
        struct in_addr  addr;
125
 
        struct hostent* host;
 
150
        struct hostent  *hst;
126
151
 
127
152
        assert(ip);
128
153
 
129
 
        if(inet_aton(ip, &addr) != 0)
130
 
        {
131
 
                host = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
132
 
                if(host)        return host;
133
 
        }
134
 
 
135
 
        return (struct hostent*) NULL;
 
154
        if(inet_aton(ip, &addr) == 0)
 
155
        {
 
156
                host[0] = '\0';
 
157
                return;
 
158
        }
 
159
 
 
160
        if(NULL == (hst = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET)))
 
161
        {
 
162
                host[0] = '\0';
 
163
                return;
 
164
        }
 
165
 
 
166
        zbx_strlcpy(host, hst->h_name, hostlen);
136
167
}
137
 
#endif /* WINDOWS */
 
168
#endif /*HAVE_IPV6*/
 
169
#endif /* _WINDOWS */
138
170
 
139
171
/******************************************************************************
140
172
 *                                                                            *
165
197
 
166
198
        host = gethostbyaddr((char *)&addr, 4, AF_INET);
167
199
 
168
 
        if(host)        return host;
 
200
        if(host)        return host;
169
201
 
170
202
 
171
203
        zbx_set_tcp_strerror("gethost() failed for address '%s' [%s]", hostname, strerror_from_system(zbx_sock_last_error()));
198
230
{
199
231
        WSADATA sockInfo;
200
232
 
201
 
        switch(WSAStartup(0x0002,&sockInfo))
 
233
        switch(WSAStartup(MAKEWORD(2, 2),&sockInfo))
202
234
        {
203
235
                case WSASYSNOTREADY:
204
236
                        zbx_set_tcp_strerror("Underlying network subsystem is not ready for network communication.");
232
264
 *                                                                            *
233
265
 * Parameters:                                                                *
234
266
 *                                                                            *
235
 
 * Return value:                                                              * 
 
267
 * Return value:                                                              *
236
268
 *                                                                            *
237
269
 * Author: Alexei Vladishev                                                   *
238
270
 *                                                                            *
254
286
 *                                                                            *
255
287
 * Parameters:                                                                *
256
288
 *                                                                            *
257
 
 * Return value:                                                              * 
 
289
 * Return value:                                                              *
258
290
 *                                                                            *
259
291
 * Author: Eugene Grigorjev                                                   *
260
292
 *                                                                            *
275
307
 *                                                                            *
276
308
 * Parameters:                                                                *
277
309
 *                                                                            *
278
 
 * Return value: sockfd - open socket                                         * 
 
310
 * Return value: sockfd - open socket                                         *
279
311
 *               FAIL - an error occured                                      *
280
312
 *                                                                            *
281
313
 * Author: Alexei Vladishev                                                   *
283
315
 * Comments:                                                                  *
284
316
 *                                                                            *
285
317
 ******************************************************************************/
286
 
int     zbx_tcp_connect(zbx_sock_t *s, const char *ip, unsigned short port)
287
 
{
288
 
        ZBX_SOCKADDR    myaddr_in;
 
318
#if defined(HAVE_IPV6)
 
319
int     zbx_tcp_connect(zbx_sock_t *s,
 
320
        const char      *ip, 
 
321
        unsigned short  port,
 
322
        int             timeout
 
323
        )
 
324
{
 
325
        int     ret = FAIL;
 
326
        struct  addrinfo *ai = NULL, hints;
 
327
        char    service[MAX_STRING_LEN];
 
328
 
 
329
        ZBX_TCP_START();
 
330
 
 
331
        zbx_tcp_clean(s);
 
332
 
 
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;
 
337
 
 
338
        if (0 != getaddrinfo(ip, service, &hints, &ai)) {
 
339
                zbx_set_tcp_strerror("Cannot resolve [%s]", ip);
 
340
                goto out;
 
341
        }
 
342
 
 
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()));
 
345
                goto out;
 
346
        }
 
347
 
 
348
        if (0 != timeout) {
 
349
                s->timeout = timeout;
 
350
#if defined(_WINDOWS)
 
351
                timeout *= 1000;
 
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()));
 
354
 
 
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()));
 
357
#else
 
358
                alarm(timeout);
 
359
#endif
 
360
        }
 
361
 
 
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()));
 
364
                zbx_tcp_close(s);
 
365
                goto out;
 
366
        }
 
367
 
 
368
        ret = SUCCEED;
 
369
out:
 
370
        if (NULL != ai)
 
371
                freeaddrinfo(ai);
 
372
        return ret;
 
373
}
 
374
#else
 
375
int     zbx_tcp_connect(zbx_sock_t *s,
 
376
        const char      *ip,
 
377
        unsigned short  port,
 
378
        int             timeout
 
379
        )
 
380
{
289
381
        ZBX_SOCKADDR    servaddr_in;
290
 
 
291
382
        struct  hostent *hp;
292
383
 
293
384
        ZBX_TCP_START();
294
385
 
295
386
        zbx_tcp_clean(s);
296
387
 
297
 
        if(NULL == (hp = zbx_gethost(ip)))
298
 
        {
 
388
        if (NULL == (hp = zbx_gethost(ip))) {
299
389
                zbx_set_tcp_strerror("Cannot resolve [%s]", ip);
300
390
                return  FAIL;
301
391
        }
304
394
        servaddr_in.sin_addr.s_addr     = ((struct in_addr *)(hp->h_addr))->s_addr;
305
395
        servaddr_in.sin_port            = htons(port);
306
396
 
307
 
        if( ZBX_SOCK_ERROR == (s->socket = socket(AF_INET,SOCK_STREAM,0)) )
308
 
        {
 
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()));
310
399
                return  FAIL;
311
400
        }
312
401
 
313
 
        myaddr_in.sin_family            = AF_INET;
314
 
        myaddr_in.sin_port                      = 0;
315
 
        myaddr_in.sin_addr.s_addr       = INADDR_ANY;
316
 
 
317
 
        if( ZBX_TCP_ERROR == connect(s->socket,(struct sockaddr *)&servaddr_in,sizeof(ZBX_SOCKADDR)) )
318
 
        {
 
402
        if (0 != timeout) {
 
403
                s->timeout = timeout;
 
404
#if defined(_WINDOWS)
 
405
                timeout *= 1000;
 
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()));
 
408
 
 
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()));
 
411
#else
 
412
                alarm(timeout);
 
413
#endif
 
414
        }
 
415
 
 
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);
321
419
                return  FAIL;
323
421
 
324
422
        return SUCCEED;
325
423
}
326
 
 
 
424
#endif /*HAVE_IPV6*/
327
425
/******************************************************************************
328
426
 *                                                                            *
329
427
 * Function: zbx_tcp_send                                                     *
332
430
 *                                                                            *
333
431
 * Parameters:                                                                *
334
432
 *                                                                            *
335
 
 * Return value: SUCCEED - success                                            * 
 
433
 * Return value: SUCCEED - success                                            *
336
434
 *               FAIL - an error occured                                      *
337
435
 *                                                                            *
338
436
 * Author: Eugene Grigorjev                                                   *
346
444
#define ZBX_TCP_HEADER                  ZBX_TCP_HEADER_DATA ZBX_TCP_HEADER_VERSION
347
445
#define ZBX_TCP_HEADER_LEN              5
348
446
 
349
 
int     zbx_tcp_send_ext(zbx_sock_t *s, const char *data, unsigned char flags)
 
447
int     zbx_tcp_send_ext(zbx_sock_t *s, const char *data, unsigned char flags)
350
448
{
351
449
        zbx_uint64_t    len64;
352
450
 
377
475
 
378
476
        while(written < (ssize_t)strlen(data))
379
477
        {
380
 
                if( ZBX_TCP_ERROR == (i = ZBX_TCP_WRITE(s->socket, data+written,strlen(data)-written)) )
 
478
                if( ZBX_TCP_ERROR == (i = ZBX_TCP_WRITE(s->socket, data+written,(int)(strlen(data)-written))) )
381
479
                {
382
480
                        zbx_set_tcp_strerror("ZBX_TCP_WRITE() failed [%s]", strerror_from_system(zbx_sock_last_error()));
383
481
                        return  FAIL;
403
501
 * Comments:                                                                  *
404
502
 *                                                                            *
405
503
 ******************************************************************************/
406
 
void    zbx_tcp_close(zbx_sock_t *s)
 
504
void    zbx_tcp_close(zbx_sock_t *s)
407
505
{
408
506
        zbx_tcp_unaccept(s);
409
507
        
410
508
        zbx_tcp_free(s);
411
509
 
 
510
#if !defined(_WINDOWS)
 
511
        if (0 != s->timeout)
 
512
                alarm(0);
 
513
#endif
412
514
        zbx_sock_close(s->socket);
413
515
}
414
516
 
420
522
 *                                                                            *
421
523
 * Parameters:                                                                *
422
524
 *                                                                            *
423
 
 * Return value: SUCCEED - success                                            * 
 
525
 * Return value: SUCCEED - success                                            *
424
526
 *               FAIL - an error occured                                      *
425
527
 *                                                                            *
426
528
 * Author: Alexei Vladishev                                                   *
428
530
 * Comments:                                                                  *
429
531
 *                                                                            *
430
532
 ******************************************************************************/
431
 
int zbx_tcp_listen(
432
 
        zbx_sock_t              *s,
433
 
        const char              *listen_ip,
434
 
        unsigned short  listen_port
435
 
        )
436
 
{
437
 
        ZBX_SOCKADDR serv_addr;
438
 
        int     on;
439
 
 
440
 
        ZBX_TCP_START();
441
 
 
442
 
        zbx_tcp_clean(s);
443
 
 
444
 
        if( ZBX_SOCK_ERROR == (s->socket = socket(AF_INET,SOCK_STREAM,0)) )
445
 
        {
446
 
                zbx_set_tcp_strerror("Cannot create socket [%s:%u] [%s]", listen_ip, listen_port ,strerror_from_system(zbx_sock_last_error()));
447
 
                return  FAIL;
 
533
#if defined(HAVE_IPV6)
 
534
int zbx_tcp_listen(
 
535
        zbx_sock_t      *s,
 
536
        const char      *listen_ip,
 
537
        unsigned short  listen_port
 
538
        )
 
539
{
 
540
        struct          addrinfo hints, *ai = NULL, *current_ai;
 
541
        char            port[MAX_STRING_LEN];
 
542
        int             e, on, ret = FAIL;
 
543
 
 
544
        ZBX_TCP_START();
 
545
 
 
546
        zbx_tcp_clean(s);
 
547
 
 
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)))
 
554
        {
 
555
                zbx_set_tcp_strerror("Cannot resolve address [[%s]:%u], error %d: %s", listen_ip, listen_port, e, gai_strerror(e));
 
556
                goto out;
 
557
        }
 
558
 
 
559
        for(s->num_socks = 0, current_ai = ai; current_ai != NULL; current_ai = current_ai->ai_next)
 
560
        {
 
561
                if(s->num_socks == FD_SETSIZE) {
 
562
                        break;
 
563
                }
 
564
                /* This example only supports PF_INET and PF_INET6. */
 
565
                if((current_ai->ai_family != PF_INET) && (current_ai->ai_family != PF_INET6))
 
566
                        continue;
 
567
 
 
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()));
 
570
                        continue;
 
571
                }
 
572
 
 
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 */
 
576
                on = 1;
 
577
                if(setsockopt(s->sockets[s->num_socks], SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)) == ZBX_TCP_ERROR)
 
578
                {
 
579
                        zbx_set_tcp_strerror("setsockopt() failed with error %d: %s", zbx_sock_last_error(), strerror_from_system(zbx_sock_last_error()));
 
580
                }
 
581
 
 
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]);
 
586
                        continue;
 
587
                }
 
588
 
 
589
                if(ZBX_SOCK_ERROR == listen(s->sockets[s->num_socks], SOMAXCONN) )
 
590
                {
 
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]);
 
593
                        continue;
 
594
                }
 
595
 
 
596
                s->num_socks++;
 
597
        }
 
598
 
 
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);
 
601
                goto out;
 
602
        }
 
603
        ret = SUCCEED;
 
604
out:
 
605
        if (NULL != ai)
 
606
                freeaddrinfo(ai);
 
607
        return ret;
 
608
}
 
609
#else
 
610
int zbx_tcp_listen(
 
611
        zbx_sock_t      *s,
 
612
        const char      *listen_ip,
 
613
        unsigned short  listen_port
 
614
        )
 
615
{
 
616
        ZBX_SOCKADDR    serv_addr;
 
617
        int             on, res = FAIL;
 
618
 
 
619
        ZBX_TCP_START();
 
620
 
 
621
        zbx_tcp_clean(s);
 
622
 
 
623
        if(ZBX_SOCK_ERROR == (s->socket = socket(AF_INET,SOCK_STREAM,0)))
 
624
        {
 
625
                zbx_set_tcp_strerror("Cannot create socket [%s:%u] [%s]", listen_ip, listen_port, strerror_from_system(zbx_sock_last_error()));
 
626
                goto out;
448
627
        }
449
628
 
450
629
        /* Enable address reuse */
461
640
 
462
641
        serv_addr.sin_family            = AF_INET;
463
642
        serv_addr.sin_addr.s_addr       = listen_ip ? inet_addr(listen_ip) : htonl(INADDR_ANY);
464
 
        serv_addr.sin_port                      = htons((unsigned short)listen_port);
 
643
        serv_addr.sin_port              = htons((unsigned short)listen_port);
465
644
 
466
645
        /* Bind socket */
467
646
        if (ZBX_SOCK_ERROR == bind(s->socket,(struct sockaddr *)&serv_addr,sizeof(ZBX_SOCKADDR)) )
471
650
                                listen_ip ? listen_ip : "[ANY]",
472
651
                                strerror_from_system(zbx_sock_last_error()));
473
652
 
474
 
                return  FAIL;
 
653
                goto out;
475
654
        }
476
655
 
477
656
        if( ZBX_SOCK_ERROR == listen(s->socket, SOMAXCONN) )
478
657
        {
479
658
                zbx_set_tcp_strerror("Listen failed. [%s]", strerror_from_system(zbx_sock_last_error()));
480
 
                return  FAIL;
 
659
                goto out;
481
660
        }
482
 
        return SUCCEED;
 
661
        res = SUCCEED;
 
662
out:
 
663
        return res;
483
664
}
484
 
 
 
665
#endif /*HAVE_IPV6*/
485
666
/******************************************************************************
486
667
 *                                                                            *
487
668
 * Function: zbx_tcp_accept                                                   *
498
679
 * Comments:                                                                  *
499
680
 *                                                                            *
500
681
 ******************************************************************************/
 
682
#if defined(HAVE_IPV6)
 
683
int     zbx_tcp_accept(zbx_sock_t *s)
 
684
{
 
685
        struct sockaddr_storage serv_addr;
 
686
        fd_set                  sock_set;
 
687
        ZBX_SOCKET              accepted_socket;
 
688
        socklen_t               nlen;
 
689
        int                     i, n = 0;
 
690
 
 
691
        zbx_tcp_unaccept(s);
 
692
 
 
693
        FD_ZERO(&sock_set);
 
694
 
 
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.
 
698
 
 
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. */
 
702
 
 
703
        for(i = 0; i < s->num_socks; i++) {
 
704
#if !defined(_WINDOWS)
 
705
                if(s->sockets[i] > n)
 
706
                        n = s->sockets[i];
 
707
#endif
 
708
                if(FD_ISSET(s->sockets[i], &sock_set))
 
709
                        break;
 
710
        }
 
711
 
 
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()));
 
717
                        return  FAIL;
 
718
                }
 
719
        }
 
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);
 
723
                        break;
 
724
                }
 
725
        }
 
726
 
 
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()));
 
732
                return FAIL;
 
733
        }
 
734
 
 
735
        s->socket2      = s->socket;            /* remember main socket */
 
736
        s->socket       = accepted_socket;      /* replace socket to accepted */
 
737
        s->accepted     = 1;
 
738
 
 
739
        return SUCCEED;
 
740
}
 
741
#else
501
742
int     zbx_tcp_accept(zbx_sock_t *s)
502
743
{
503
744
        ZBX_SOCKADDR    serv_addr;
504
745
        ZBX_SOCKET      accepted_socket;
505
 
 
506
746
        socklen_t       nlen;
507
747
 
508
 
        nlen = sizeof(ZBX_SOCKADDR);
 
748
        nlen = sizeof(serv_addr);
509
749
 
510
750
        zbx_tcp_unaccept(s);
511
751
 
517
757
 
518
758
        s->socket2      = s->socket;            /* remember main socket */
519
759
        s->socket       = accepted_socket;      /* replace socket to accepted */
520
 
        s->accepted = 1;
 
760
        s->accepted     = 1;
521
761
 
522
762
        return  SUCCEED;
523
763
}
524
 
 
 
764
#endif /* HAVE_IPV6 */
525
765
/******************************************************************************
526
766
 *                                                                            *
527
767
 * Function: zbx_tcp_unaccept                                                 *
552
792
 
553
793
/******************************************************************************
554
794
 *                                                                            *
555
 
 * Function: zbx_tcp_close                                                    *
 
795
 * Function: zbx_tcp_free                                                     *
556
796
 *                                                                            *
557
797
 * Purpose: close open socket                                                 *
558
798
 *                                                                            *
565
805
 * Comments:                                                                  *
566
806
 *                                                                            *
567
807
 ******************************************************************************/
568
 
void    zbx_tcp_free(zbx_sock_t *s)
 
808
void    zbx_tcp_free(zbx_sock_t *s)
569
809
{
570
810
        zbx_free(s->buf_dyn);
571
811
}
578
818
 *                                                                            *
579
819
 * Parameters:                                                                *
580
820
 *                                                                            *
581
 
 * Return value: SUCCEED - success                                            * 
 
821
 * Return value: SUCCEED - success                                            *
582
822
 *               FAIL - an error occured                                      *
583
823
 *                                                                            *
584
824
 * Author: Eugene Grigorjev                                                   *
722
962
        int allow_if_empty
723
963
        )
724
964
{
725
 
        ZBX_SOCKADDR name;
 
965
#if defined(HAVE_IPV6)
 
966
        struct          sockaddr_storage name;
 
967
        struct          addrinfo hints, *ai = NULL;
 
968
#else
 
969
        ZBX_SOCKADDR    name;
 
970
        struct          hostent *hp;
 
971
        char            *sip;
 
972
        int             i[4], j[4];
 
973
#endif
726
974
        socklen_t       nlen;
727
975
 
728
 
        struct  hostent *hp;
729
 
 
730
 
        char
731
 
                tmp[MAX_STRING_LEN], 
 
976
        char    tmp[MAX_STRING_LEN], 
732
977
                sname[MAX_STRING_LEN],
733
 
                *sip, 
734
 
                *host;
 
978
                *start = NULL,
 
979
                *end = NULL,
 
980
                c = '\0';
735
981
 
736
982
        zabbix_log( LOG_LEVEL_DEBUG, "In check_security()");
737
983
 
739
985
        {
740
986
                return SUCCEED;
741
987
        }
742
 
        nlen = sizeof(ZBX_SOCKADDR);
743
 
        if( ZBX_TCP_ERROR == getpeername(s->socket,  (struct sockaddr*)&name, &nlen))
 
988
        nlen = sizeof(name);
 
989
        if( ZBX_TCP_ERROR == getpeername(s->socket, (struct sockaddr*)&name, &nlen))
744
990
        {
745
991
                zbx_set_tcp_strerror("Connection rejected. Getpeername failed [%s]", strerror_from_system(zbx_sock_last_error()));
746
992
                return FAIL;
747
993
        }
748
994
        else
749
995
        {
 
996
#if !defined(HAVE_IPV6)
750
997
                strcpy(sname, inet_ntoa(name.sin_addr));
751
998
 
 
999
                if(sscanf(sname, "%d.%d.%d.%d", &i[0], &i[1], &i[2], &i[3]) != 4)
 
1000
                {
 
1001
                        return FAIL;
 
1002
                }
 
1003
#endif /*HAVE_IPV6*/
752
1004
                strscpy(tmp,ip_list);
753
1005
 
754
 
                host = (char *)strtok(tmp,",");
755
 
 
756
 
                while( NULL != host )
 
1006
                for(start = tmp; start[0] != '\0';)
757
1007
                {
 
1008
                        end = strchr(start, ',');
 
1009
 
 
1010
                        if(end != NULL)
 
1011
                        {
 
1012
                                c = end[0];
 
1013
                                end[0] = '\0';
 
1014
                        }
 
1015
 
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))
 
1021
                        {
 
1022
                                if(ai->ai_family == name.ss_family)
 
1023
                                {
 
1024
                                        switch(ai->ai_family)
 
1025
                                        {
 
1026
                                                case AF_INET  :
 
1027
                                                        if(((struct sockaddr_in*)&name)->sin_addr.s_addr == ((struct sockaddr_in*)ai->ai_addr)->sin_addr.s_addr)
 
1028
                                                        {
 
1029
                                                                freeaddrinfo(ai);
 
1030
                                                                return SUCCEED;
 
1031
                                                        }
 
1032
                                                case AF_INET6 :
 
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)))
 
1036
                                                        {
 
1037
                                                                freeaddrinfo(ai);
 
1038
                                                                return SUCCEED;
 
1039
                                                        }
 
1040
                                        }
 
1041
                                }
 
1042
                                freeaddrinfo(ai);
 
1043
                        }
 
1044
#else
 
1045
                        if( 0 != (hp = zbx_gethost(start)))
760
1046
                        {
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)
763
1049
                                {
764
 
                                        return  SUCCEED;
 
1050
                                        if(i[0] == j[0] && i[1] == j[1] && i[2] == j[2] && i[3] == j[3])
 
1051
                                        {
 
1052
                                                return SUCCEED;
 
1053
                                        }
765
1054
                                }
766
1055
                        }
767
 
                        host = (char *)strtok(NULL,",");
768
 
                }
769
 
        }
 
1056
#endif /*HAVE_IPV6*/
 
1057
                        if(end != NULL)
 
1058
                        {
 
1059
                                end[0] = c;
 
1060
                                start = end + 1;
 
1061
                        }
 
1062
                        else
 
1063
                        {
 
1064
                                break;
 
1065
                        }
 
1066
                }
 
1067
 
 
1068
                if(end != NULL)
 
1069
                {
 
1070
                        end[0] = c;
 
1071
                }
 
1072
        }
 
1073
#if defined(HAVE_IPV6)
 
1074
        if(0 == getnameinfo((struct sockaddr*)&name, sizeof(name), sname, sizeof(sname), NULL, 0, NI_NUMERICHOST))
 
1075
        {
 
1076
                zbx_set_tcp_strerror("Connection from [%s] rejected. Allowed server is [%s] ",sname, ip_list);
 
1077
        }
 
1078
        else
 
1079
        {
 
1080
                zbx_set_tcp_strerror("Connection rejected. Allowed server is [%s] ", ip_list);
 
1081
        }
 
1082
#else
770
1083
        zbx_set_tcp_strerror("Connection from [%s] rejected. Allowed server is [%s] ",sname, ip_list);
 
1084
#endif /*HAVE_IPV6*/
771
1085
        return  FAIL;
772
1086
}
773