/*
- Bacula® - The Network Backup Solution
-
- Copyright (C) 2000-2011 Free Software Foundation Europe e.V.
-
- The main author of Bacula is Kern Sibbald, with contributions from
- many others, a complete list can be found in the file AUTHORS.
- This program is Free Software; you can redistribute it and/or
- modify it under the terms of version three of the GNU Affero General Public
- License as published by the Free Software Foundation and included
- in the file LICENSE.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
- Bacula® is a registered trademark of Kern Sibbald.
- The licensor of Bacula is the Free Software Foundation Europe
- (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
- Switzerland, email:ftf@fsfeurope.org.
+ Bacula(R) - The Network Backup Solution
+
+ Copyright (C) 2000-2016 Kern Sibbald
+
+ The original author of Bacula is Kern Sibbald, with contributions
+ from many others, a complete list can be found in the file AUTHORS.
+
+ You may use this file and others of this release according to the
+ license defined in the LICENSE file, which includes the Affero General
+ Public License, v3.0 ("AGPLv3") and some additional permissions and
+ terms pursuant to its AGPLv3 Section 7.
+
+ This notice must be preserved when any source code is
+ conveyed and/or propagated.
+
+ Bacula(R) is a registered trademark of Kern Sibbald.
*/
/*
* Originally written by Kern Sibbald for inclusion in apcupsd,
}
}
-/*
- 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
+ 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))
{
int newsockfd, stat;
socklen_t clilen;
- struct sockaddr cli_addr; /* client's address */
+ struct sockaddr_storage clientaddr; /* client's address */
int tlog;
int turnon = 1;
#ifdef HAVE_LIBWRAP
struct request_info request;
#endif
- IPADDR *p;
+ IPADDR *addr;
struct s_sockfd {
dlink link; /* this MUST be the first item */
int fd;
dlist sockfds;
char allbuf[256 * 10];
- Dmsg1(100, "Addresses %s\n", build_addresses_str(addrs, allbuf, sizeof(allbuf)));
-
- foreach_dlist(p, addrs) {
+ remove_duplicate_addresses(addrs);
+ Dmsg1(20, "Addresses %s\n", build_addresses_str(addrs, allbuf, sizeof(allbuf)));
+ /*
+ * Listen on each address provided.
+ */
+ foreach_dlist(addr, addrs) {
/* 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 = addr->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(addr->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)),
+ addr->build_address_str(curbuf, sizeof(curbuf)),
build_addresses_str(addrs, allbuf, sizeof(allbuf)));
}
bmicrosleep(10, 0);
be.bstrerror());
}
- 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) {
+ int tmax = 1 * (60 / 5); /* wait 1 minute max */
+ for (tlog = 0; bind(fd_ptr->fd, addr->get_sockaddr(), addr->get_sockaddr_len()) == SOCKET_ERROR; tlog -= 5) {
berrno be;
if (tlog <= 0) {
- tlog = 2 * 60; /* Complain every 2 minutes */
+ tlog = 1 * 60; /* Complain every 1 minute */
Emsg2(M_WARNING, 0, _("Cannot bind port %d: ERR=%s: Retrying ...\n"),
ntohs(fd_ptr->port), be.bstrerror());
+ Dmsg2(20, "Cannot bind port %d: ERR=%s: Retrying ...\n",
+ ntohs(fd_ptr->port), be.bstrerror());
+
}
bmicrosleep(5, 0);
if (--tmax <= 0) {
Emsg2(M_ABORT, 0, _("Cannot bind port %d: ERR=%s.\n"), ntohs(fd_ptr->port),
be.bstrerror());
+ Pmsg2(000, "Aborting cannot bind port %d: ERR=%s.\n", ntohs(fd_ptr->port),
+ be.bstrerror());
}
}
- listen(fd_ptr->fd, 50); /* tell system we are ready */
- sockfds.append(fd_ptr);
+ if (listen(fd_ptr->fd, 50) < 0) { /* tell system we are ready */
+ berrno be;
+ Emsg2(M_ABORT, 0, _("Cannot bind port %d: ERR=%s.\n"), ntohs(fd_ptr->port),
+ be.bstrerror());
+ } else {
+ sockfds.append(fd_ptr);
+ }
+ }
+ if (sockfds.size() == 0) {
+ Emsg0(M_ABORT, 0, _("No addr/port found to listen on.\n"));
}
/* Start work queue thread */
if ((stat = workq_init(client_wq, max_clients, handle_client_request)) != 0) {
if (FD_ISSET(fd_ptr->fd, &sockset)) {
/* Got a connection, now accept it. */
do {
- clilen = sizeof(cli_addr);
- newsockfd = accept(fd_ptr->fd, &cli_addr, &clilen);
- } while (newsockfd < 0 && errno == EINTR);
- if (newsockfd < 0) {
+ clilen = sizeof(clientaddr);
+ newsockfd = baccept(fd_ptr->fd, (struct sockaddr *)&clientaddr, &clilen);
+ newsockfd = set_socket_errno(newsockfd);
+ } while (newsockfd == SOCKET_ERROR && (errno == EINTR || errno == EAGAIN));
+ if (newsockfd == SOCKET_ERROR) {
+ Dmsg2(20, "Accept=%d errno=%d\n", newsockfd, errno);
continue;
}
#ifdef HAVE_LIBWRAP
V(mutex);
Jmsg2(NULL, M_SECURITY, 0,
_("Connection from %s:%d refused by hosts.access\n"),
- sockaddr_to_ascii(&cli_addr, buf, sizeof(buf)),
- sockaddr_get_port(&cli_addr));
+ sockaddr_to_ascii((struct sockaddr *)&clientaddr,
+ sizeof(clientaddr), buf, sizeof(buf)),
+ sockaddr_get_port((struct sockaddr *)&clientaddr));
close(newsockfd);
continue;
}
/* see who client is. i.e. who connected to us. */
P(mutex);
- sockaddr_to_ascii(&cli_addr, buf, sizeof(buf));
+ sockaddr_to_ascii((struct sockaddr *)&clientaddr, sizeof(clientaddr), buf, sizeof(buf));
V(mutex);
BSOCK *bs;
- bs = init_bsock(NULL, newsockfd, "client", buf, fd_ptr->port, &cli_addr);
+ bs = init_bsock(NULL, newsockfd, "client", buf, ntohs(fd_ptr->port),
+ (struct sockaddr *)&clientaddr);
if (bs == NULL) {
Jmsg0(NULL, M_ABORT, 0, _("Could not create client BSOCK.\n"));
}