From 2ebe1807db9d98ac088e78ddad4468cc05a279af Mon Sep 17 00:00:00 2001 From: Marco van Wieringen Date: Mon, 25 Jun 2012 19:42:28 +0200 Subject: [PATCH] First try at fixing bug #1897 Remove any duplicate addresses on a addr dlist. For listening it makes no sense as we cannot listen multiple times on the same address with different sockets. And for outbound connecting its also kind of strange to try to connect multiple times to the same address. --- bacula/src/lib/bnet_server.c | 49 +++++++++++++++++++++++------------- bacula/src/lib/bsock.c | 15 ++++++++++- bacula/src/lib/protos.h | 2 +- 3 files changed, 47 insertions(+), 19 deletions(-) diff --git a/bacula/src/lib/bnet_server.c b/bacula/src/lib/bnet_server.c index 0939417281..32dbe7ae37 100644 --- a/bacula/src/lib/bnet_server.c +++ b/bacula/src/lib/bnet_server.c @@ -64,15 +64,16 @@ void bnet_stop_thread_server(pthread_t tid) } /* - Become Threaded Network Server - This function is able to handle multiple server ips in - ipv4 and ipv6 style. The Addresse are give in a comma - seperated string in bind_addr - In the moment it is inpossible to bind different ports. -*/ -void -bnet_thread_server(dlist *addrs, int max_clients, workq_t *client_wq, - void *handle_client_request(void *bsock)) + * Become Threaded Network Server + * + * This function is able to handle multiple server ips in + * ipv4 and ipv6 style. The Addresse are give in a comma + * seperated string in bind_addr + * + * At the moment it is inpossible to bind different ports. + */ +void bnet_thread_server(dlist *addr_list, int max_clients, workq_t *client_wq, + void *handle_client_request(void *bsock)) { int newsockfd, stat; socklen_t clilen; @@ -82,7 +83,7 @@ bnet_thread_server(dlist *addrs, int max_clients, workq_t *client_wq, #ifdef HAVE_LIBWRAP struct request_info request; #endif - IPADDR *p; + IPADDR *ipaddr, *next; struct s_sockfd { dlink link; /* this MUST be the first item */ int fd; @@ -92,23 +93,37 @@ bnet_thread_server(dlist *addrs, int max_clients, workq_t *client_wq, dlist sockfds; char allbuf[256 * 10]; - Dmsg1(100, "Addresses %s\n", build_addresses_str(addrs, allbuf, sizeof(allbuf))); - foreach_dlist(p, addrs) { + /* + * Remove any duplicate addresses. + */ + for (ipaddr = (IPADDR *)addr_list->first(); ipaddr; ipaddr = (IPADDR *)addr_list->next(ipaddr)) { + for (next = (IPADDR *)addr_list->next(ipaddr); next; next = (IPADDR *)addr_list->next(next)) { + if (ipaddr->get_sockaddr_len() == next->get_sockaddr_len() && + !memcmp(ipaddr->get_sockaddr(), next->get_sockaddr(), + ipaddr->get_sockaddr_len())) { + addr_list->remove(next); + } + } + } + + Dmsg1(100, "Addresses %s\n", build_addresses_str(addr_list, allbuf, sizeof(allbuf))); + + foreach_dlist(ipaddr, addr_list) { /* Allocate on stack from -- no need to free */ fd_ptr = (s_sockfd *)alloca(sizeof(s_sockfd)); - fd_ptr->port = p->get_port_net_order(); + fd_ptr->port = ipaddr->get_port_net_order(); /* * Open a TCP socket */ - for (tlog= 60; (fd_ptr->fd=socket(p->get_family(), SOCK_STREAM, 0)) < 0; tlog -= 10) { + for (tlog= 60; (fd_ptr->fd=socket(ipaddr->get_family(), SOCK_STREAM, 0)) < 0; tlog -= 10) { if (tlog <= 0) { berrno be; char curbuf[256]; Emsg3(M_ABORT, 0, _("Cannot open stream socket. ERR=%s. Current %s All %s\n"), be.bstrerror(), - p->build_address_str(curbuf, sizeof(curbuf)), - build_addresses_str(addrs, allbuf, sizeof(allbuf))); + ipaddr->build_address_str(curbuf, sizeof(curbuf)), + build_addresses_str(addr_list, allbuf, sizeof(allbuf))); } bmicrosleep(10, 0); } @@ -123,7 +138,7 @@ bnet_thread_server(dlist *addrs, int max_clients, workq_t *client_wq, } int tmax = 30 * (60 / 5); /* wait 30 minutes max */ - for (tlog = 0; bind(fd_ptr->fd, p->get_sockaddr(), p->get_sockaddr_len()) < 0; tlog -= 5) { + for (tlog = 0; bind(fd_ptr->fd, ipaddr->get_sockaddr(), ipaddr->get_sockaddr_len()) < 0; tlog -= 5) { berrno be; if (tlog <= 0) { tlog = 2 * 60; /* Complain every 2 minutes */ diff --git a/bacula/src/lib/bsock.c b/bacula/src/lib/bsock.c index 0eeb74be48..c630bfbaf2 100644 --- a/bacula/src/lib/bsock.c +++ b/bacula/src/lib/bsock.c @@ -192,7 +192,7 @@ bool BSOCK::open(JCR *jcr, const char *name, char *host, char *service, { int sockfd = -1; dlist *addr_list; - IPADDR *ipaddr; + IPADDR *ipaddr, *next; bool connected = false; int turnon = 1; const char *errstr; @@ -212,6 +212,19 @@ bool BSOCK::open(JCR *jcr, const char *name, char *host, char *service, return false; } + /* + * Remove any duplicate addresses. + */ + for (ipaddr = (IPADDR *)addr_list->first(); ipaddr; ipaddr = (IPADDR *)addr_list->next(ipaddr)) { + for (next = (IPADDR *)addr_list->next(ipaddr); next; next = (IPADDR *)addr_list->next(next)) { + if (ipaddr->get_sockaddr_len() == next->get_sockaddr_len() && + !memcmp(ipaddr->get_sockaddr(), next->get_sockaddr(), + ipaddr->get_sockaddr_len())) { + addr_list->remove(next); + } + } + } + foreach_dlist(ipaddr, addr_list) { ipaddr->set_port_net(htons(port)); char allbuf[256 * 10]; diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index e161158b4d..c956eccb35 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -246,7 +246,7 @@ void set_db_type (const char *name); void register_message_callback(void msg_callback(int type, char *msg)); /* bnet_server.c */ -void bnet_thread_server(dlist *addr, int max_clients, workq_t *client_wq, +void bnet_thread_server(dlist *addr_list, int max_clients, workq_t *client_wq, void *handle_client_request(void *bsock)); void bnet_stop_thread_server(pthread_t tid); void bnet_server (int port, void handle_client_request(BSOCK *bsock)); -- 2.39.5