]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/bnet.c
dhb Medialist : created context menu function and moved lines which create
[bacula/bacula] / bacula / src / lib / bnet.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation plus additions
11    that are listed in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of John Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  * Network Utility Routines
30  *
31  *  by Kern Sibbald
32  *
33  * Adapted and enhanced for Bacula, originally written
34  * for inclusion in the Apcupsd package
35  *
36  *   Version $Id$
37  */
38
39
40 #include "bacula.h"
41 #include "jcr.h"
42 #include <netdb.h>
43
44 extern time_t watchdog_time;
45
46 #ifndef   INADDR_NONE
47 #define   INADDR_NONE    -1
48 #endif
49
50 #ifdef HAVE_WIN32
51 #define socketRead(fd, buf, len)  recv(fd, buf, len, 0)
52 #define socketWrite(fd, buf, len) send(fd, buf, len, 0)
53 #define socketClose(fd)           closesocket(fd)
54 #else
55 #define socketRead(fd, buf, len)  read(fd, buf, len)
56 #define socketWrite(fd, buf, len) write(fd, buf, len)
57 #define socketClose(fd)           close(fd)
58 #endif
59
60 static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
61
62 /*
63  * Read a nbytes from the network.
64  * It is possible that the total bytes require in several
65  * read requests
66  */
67
68 int32_t read_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes)
69 {
70    int32_t nleft, nread;
71
72 #ifdef HAVE_TLS
73    if (bsock->tls) {
74       /* TLS enabled */
75       return (tls_bsock_readn(bsock, ptr, nbytes));
76    }
77 #endif /* HAVE_TLS */
78
79    nleft = nbytes;
80    while (nleft > 0) {
81       errno = 0;
82       nread = socketRead(bsock->fd, ptr, nleft);
83       if (bsock->timed_out || bsock->terminated) {
84          return nread;
85       }
86       if (nread == -1) {
87          if (errno == EINTR) {
88             continue;
89          }
90          if (errno == EAGAIN) {
91             bmicrosleep(0, 200000);  /* try again in 200ms */
92             continue;
93          }
94       }
95       if (nread <= 0) {
96          return nread;             /* error, or EOF */
97       }
98       nleft -= nread;
99       ptr += nread;
100    }
101    return nbytes - nleft;          /* return >= 0 */
102 }
103
104 /*
105  * Write nbytes to the network.
106  * It may require several writes.
107  */
108
109 int32_t write_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes)
110 {
111    int32_t nleft, nwritten;
112
113    if (bsock->spool) {
114       nwritten = fwrite(ptr, 1, nbytes, bsock->spool_fd);
115       if (nwritten != nbytes) {
116          berrno be;
117          bsock->b_errno = errno;
118          Qmsg1(bsock->jcr(), M_FATAL, 0, _("Attr spool write error. ERR=%s\n"),
119                be.strerror());
120          Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes);
121          errno = bsock->b_errno;
122          return -1;
123       }
124       return nbytes;
125    }
126
127 #ifdef HAVE_TLS
128    if (bsock->tls) {
129       /* TLS enabled */
130       return (tls_bsock_writen(bsock, ptr, nbytes));
131    }
132 #endif /* HAVE_TLS */
133
134    nleft = nbytes;
135    while (nleft > 0) {
136       do {
137          errno = 0;
138          nwritten = socketWrite(bsock->fd, ptr, nleft);
139          if (bsock->timed_out || bsock->terminated) {
140             return nwritten;
141          }
142       } while (nwritten == -1 && errno == EINTR);
143       /*
144        * If connection is non-blocking, we will get EAGAIN, so
145        * use select() to keep from consuming all the CPU
146        * and try again.
147        */
148       if (nwritten == -1 && errno == EAGAIN) {
149          fd_set fdset;
150          struct timeval tv;
151
152          FD_ZERO(&fdset);
153          FD_SET((unsigned)bsock->fd, &fdset);
154          tv.tv_sec = 10;
155          tv.tv_usec = 0;
156          select(bsock->fd + 1, NULL, &fdset, NULL, &tv);
157          continue;
158       }
159       if (nwritten <= 0) {
160          return nwritten;          /* error */
161       }
162       nleft -= nwritten;
163       ptr += nwritten;
164    }
165    return nbytes - nleft;
166 }
167
168 /*
169  * Receive a message from the other end. Each message consists of
170  * two packets. The first is a header that contains the size
171  * of the data that follows in the second packet.
172  * Returns number of bytes read (may return zero)
173  * Returns -1 on signal (BNET_SIGNAL)
174  * Returns -2 on hard end of file (BNET_HARDEOF)
175  * Returns -3 on error  (BNET_ERROR)
176  *
177  *  Unfortunately, it is a bit complicated because we have these
178  *    four return types:
179  *    1. Normal data
180  *    2. Signal including end of data stream
181  *    3. Hard end of file
182  *    4. Error
183  *  Using is_bnet_stop() and is_bnet_error() you can figure this all out.
184  */
185 int32_t bnet_recv(BSOCK * bsock)
186 {
187    return bsock->recv();
188 }
189
190
191 /*
192  * Return 1 if there are errors on this bsock or it is closed,
193  *   i.e. stop communicating on this line.
194  */
195 bool is_bnet_stop(BSOCK * bsock)
196 {
197    return bsock->errors || bsock->terminated;
198 }
199
200 /*
201  * Return number of errors on socket
202  */
203 int is_bnet_error(BSOCK * bsock)
204 {
205    errno = bsock->b_errno;
206    return bsock->errors;
207 }
208
209 /*
210  * Call here after error during closing to suppress error
211  *  messages which are due to the other end shutting down too.
212  */
213 void bnet_suppress_error_messages(BSOCK * bsock, bool flag)
214 {
215    bsock->suppress_error_msgs = flag;
216 }
217
218 /*
219  * Send a message over the network. The send consists of
220  * two network packets. The first is sends a 32 bit integer containing
221  * the length of the data packet which follows.
222  *
223  * Returns: false on failure
224  *          true  on success
225  */
226 bool bnet_send(BSOCK *bsock)
227 {
228    return bsock->send();
229 }
230
231
232 /*
233  * Establish a TLS connection -- server side
234  *  Returns: true  on success
235  *           false on failure
236  */
237 #ifdef HAVE_TLS
238 bool bnet_tls_server(TLS_CONTEXT *ctx, BSOCK * bsock, alist *verify_list)
239 {
240    TLS_CONNECTION *tls;
241    
242    tls = new_tls_connection(ctx, bsock->fd);
243    if (!tls) {
244       Qmsg0(bsock->jcr(), M_FATAL, 0, _("TLS connection initialization failed.\n"));
245       return false;
246    }
247
248    bsock->tls = tls;
249
250    /* Initiate TLS Negotiation */
251    if (!tls_bsock_accept(bsock)) {
252       Qmsg0(bsock->jcr(), M_FATAL, 0, _("TLS Negotiation failed.\n"));
253       goto err;
254    }
255
256    if (verify_list) {
257       if (!tls_postconnect_verify_cn(tls, verify_list)) {
258          Qmsg1(bsock->jcr(), M_FATAL, 0, _("TLS certificate verification failed."
259                                          " Peer certificate did not match a required commonName\n"),
260                                          bsock->host());
261          goto err;
262       }
263    }
264    return true;
265
266 err:
267    free_tls_connection(tls);
268    bsock->tls = NULL;
269    return false;
270 }
271
272 /*
273  * Establish a TLS connection -- client side
274  * Returns: true  on success
275  *          false on failure
276  */
277 bool bnet_tls_client(TLS_CONTEXT *ctx, BSOCK * bsock, alist *verify_list)
278 {
279    TLS_CONNECTION *tls;
280
281    tls  = new_tls_connection(ctx, bsock->fd);
282    if (!tls) {
283       Qmsg0(bsock->jcr(), M_FATAL, 0, _("TLS connection initialization failed.\n"));
284       return false;
285    }
286
287    bsock->tls = tls;
288
289    /* Initiate TLS Negotiation */
290    if (!tls_bsock_connect(bsock)) {
291       goto err;
292    }
293
294    /* If there's an Allowed CN verify list, use that to validate the remote
295     * certificate's CN. Otherwise, we use standard host/CN matching. */
296    if (verify_list) {
297       if (!tls_postconnect_verify_cn(tls, verify_list)) {
298          Qmsg1(bsock->jcr(), M_FATAL, 0, _("TLS certificate verification failed."
299                                          " Peer certificate did not match a required commonName\n"),
300                                          bsock->host());
301          goto err;
302       }
303    } else {
304       if (!tls_postconnect_verify_host(tls, bsock->host())) {
305          Qmsg1(bsock->jcr(), M_FATAL, 0, _("TLS host certificate verification failed. Host %s did not match presented certificate\n"), 
306                bsock->host());
307          goto err;
308       }
309    }
310
311    return true;
312
313 err:
314    free_tls_connection(tls);
315    bsock->tls = NULL;
316    return false;
317 }
318 #else
319
320 bool bnet_tls_server(TLS_CONTEXT *ctx, BSOCK * bsock, alist *verify_list)
321 {
322    Jmsg(bsock->jcr(), M_ABORT, 0, _("TLS enabled but not configured.\n"));
323    return false;
324 }
325
326 bool bnet_tls_client(TLS_CONTEXT *ctx, BSOCK * bsock, alist *verify_list)
327 {
328    Jmsg(bsock->jcr(), M_ABORT, 0, _("TLS enable but not configured.\n"));
329    return false;
330 }
331
332 #endif /* HAVE_TLS */
333
334 /*
335  * Wait for a specified time for data to appear on
336  * the BSOCK connection.
337  *
338  *   Returns: 1 if data available
339  *            0 if timeout
340  *           -1 if error
341  */
342 int bnet_wait_data(BSOCK * bsock, int sec)
343 {
344    fd_set fdset;
345    struct timeval tv;
346
347    FD_ZERO(&fdset);
348    FD_SET((unsigned)bsock->fd, &fdset);
349    for (;;) {
350       tv.tv_sec = sec;
351       tv.tv_usec = 0;
352       switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
353       case 0:                      /* timeout */
354          bsock->b_errno = 0;
355          return 0;
356       case -1:
357          bsock->b_errno = errno;
358          if (errno == EINTR) {
359             continue;
360          }
361          return -1;                /* error return */
362       default:
363          bsock->b_errno = 0;
364          return 1;
365       }
366    }
367 }
368
369 /*
370  * As above, but returns on interrupt
371  */
372 int bnet_wait_data_intr(BSOCK * bsock, int sec)
373 {
374    fd_set fdset;
375    struct timeval tv;
376
377    FD_ZERO(&fdset);
378    FD_SET((unsigned)bsock->fd, &fdset);
379    tv.tv_sec = sec;
380    tv.tv_usec = 0;
381    switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
382    case 0:                      /* timeout */
383       bsock->b_errno = 0;
384       return 0;
385    case -1:
386       bsock->b_errno = errno;
387       return -1;                /* error return */
388    default:
389       bsock->b_errno = 0;
390    }
391    return 1;
392 }
393
394 #ifndef NETDB_INTERNAL
395 #define NETDB_INTERNAL  -1         /* See errno. */
396 #endif
397 #ifndef NETDB_SUCCESS
398 #define NETDB_SUCCESS   0          /* No problem. */
399 #endif
400 #ifndef HOST_NOT_FOUND
401 #define HOST_NOT_FOUND  1          /* Authoritative Answer Host not found. */
402 #endif
403 #ifndef TRY_AGAIN
404 #define TRY_AGAIN       2          /* Non-Authoritative Host not found, or SERVERFAIL. */
405 #endif
406 #ifndef NO_RECOVERY
407 #define NO_RECOVERY     3          /* Non recoverable errors, FORMERR, REFUSED, NOTIMP. */
408 #endif
409 #ifndef NO_DATA
410 #define NO_DATA         4          /* Valid name, no data record of requested type. */
411 #endif
412
413 /*
414  * Get human readable error for gethostbyname()
415  */
416 static const char *gethost_strerror()
417 {
418    const char *msg;
419    berrno be;
420    switch (h_errno) {
421    case NETDB_INTERNAL:
422       msg = be.strerror();
423       break;
424    case NETDB_SUCCESS:
425       msg = _("No problem.");
426       break;
427    case HOST_NOT_FOUND:
428       msg = _("Authoritative answer for host not found.");
429       break;
430    case TRY_AGAIN:
431       msg = _("Non-authoritative for host not found, or ServerFail.");
432       break;
433    case NO_RECOVERY:
434       msg = _("Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.");
435       break;
436    case NO_DATA:
437       msg = _("Valid name, no data record of resquested type.");
438       break;
439    default:
440       msg = _("Unknown error.");
441    }
442    return msg;
443 }
444
445
446
447
448 static IPADDR *add_any(int family)
449 {
450    IPADDR *addr = New(IPADDR(family));
451    addr->set_type(IPADDR::R_MULTIPLE);
452    addr->set_addr_any();
453    return addr;
454 }
455
456 static const char *resolv_host(int family, const char *host, dlist * addr_list)
457 {
458    struct hostent *hp;
459    const char *errmsg;
460
461    P(ip_mutex);                       /* gethostbyname() is not thread safe */
462 #ifdef HAVE_GETHOSTBYNAME2
463    if ((hp = gethostbyname2(host, family)) == NULL) {
464 #else
465    if ((hp = gethostbyname(host)) == NULL) {
466 #endif
467       /* may be the strerror give not the right result -:( */
468       errmsg = gethost_strerror();
469       V(ip_mutex);
470       return errmsg;
471    } else {
472       char **p;
473       for (p = hp->h_addr_list; *p != 0; p++) {
474          IPADDR *addr =  New(IPADDR(hp->h_addrtype));
475          addr->set_type(IPADDR::R_MULTIPLE);
476          if (addr->get_family() == AF_INET) {
477              addr->set_addr4((struct in_addr*)*p);
478          }
479 #ifdef HAVE_IPV6
480          else {
481              addr->set_addr6((struct in6_addr*)*p);
482          }
483 #endif
484          addr_list->append(addr);
485       }
486       V(ip_mutex);
487    }
488    return NULL;
489 }
490
491 /*
492  * i host = 0 mean INADDR_ANY only ipv4
493  */
494 dlist *bnet_host2ipaddrs(const char *host, int family, const char **errstr)
495 {
496    struct in_addr inaddr;
497    IPADDR *addr = 0;
498    const char *errmsg;
499 #ifdef HAVE_IPV6
500    struct in6_addr inaddr6;
501 #endif
502
503    dlist *addr_list = New(dlist(addr, &addr->link));
504    if (!host || host[0] == '\0') {
505       if (family != 0) {
506          addr_list->append(add_any(family));
507       } else {
508          addr_list->append(add_any(AF_INET));
509 #ifdef HAVE_IPV6
510          addr_list->append(add_any(AF_INET6));
511 #endif
512       }
513    } else if (inet_aton(host, &inaddr)) { /* MA Bug 4 */
514       addr = New(IPADDR(AF_INET));
515       addr->set_type(IPADDR::R_MULTIPLE);
516       addr->set_addr4(&inaddr);
517       addr_list->append(addr);
518    } else
519 #ifdef HAVE_IPV6
520    if (inet_pton(AF_INET6, host, &inaddr6) > 1) {
521       addr = New(IPADDR(AF_INET6));
522       addr->set_type(IPADDR::R_MULTIPLE);
523       addr->set_addr6(&inaddr6);
524       addr_list->append(addr);
525    } else
526 #endif
527    {
528       if (family != 0) {
529          errmsg = resolv_host(family, host, addr_list);
530          if (errmsg) {
531             *errstr = errmsg;
532             free_addresses(addr_list);
533             return 0;
534          }
535       } else {
536          errmsg = resolv_host(AF_INET, host, addr_list);
537 #ifdef HAVE_IPV6
538          if (errmsg) {
539             errmsg = resolv_host(AF_INET6, host, addr_list);
540          }
541 #endif
542          if (errmsg) {
543             *errstr = errmsg;
544             free_addresses(addr_list);
545             return 0;
546          }
547       }
548    }
549    return addr_list;
550 }
551
552 /*
553  * Open a TCP connection to the UPS network server
554  * Returns NULL
555  * Returns BSOCK * pointer on success
556  *
557  */
558 static BSOCK *bnet_open(JCR * jcr, const char *name, char *host, char *service,
559                         int port, int *fatal)
560 {
561    int sockfd = -1;
562    dlist *addr_list;
563    IPADDR *ipaddr;
564    bool connected = false;
565    int turnon = 1;
566    const char *errstr;
567    int save_errno = 0;
568
569    /*
570     * Fill in the structure serv_addr with the address of
571     * the server that we want to connect with.
572     */
573    if ((addr_list = bnet_host2ipaddrs(host, 0, &errstr)) == NULL) {
574       /* Note errstr is not malloc'ed */
575       Qmsg2(jcr, M_ERROR, 0, _("gethostbyname() for host \"%s\" failed: ERR=%s\n"),
576             host, errstr);
577       Dmsg2(100, "bnet_host2ipaddrs() for host %s failed: ERR=%s\n",
578             host, errstr);
579       *fatal = 1;
580       return NULL;
581    }
582
583    foreach_dlist(ipaddr, addr_list) {
584       ipaddr->set_port_net(htons(port));
585       char allbuf[256 * 10];
586       char curbuf[256];
587       Dmsg2(100, "Current %sAll %s\n",
588                    ipaddr->build_address_str(curbuf, sizeof(curbuf)),
589                    build_addresses_str(addr_list, allbuf, sizeof(allbuf)));
590       /* Open a TCP socket */
591       if ((sockfd = socket(ipaddr->get_family(), SOCK_STREAM, 0)) < 0) {
592          berrno be;
593          save_errno = errno;
594          *fatal = 1;
595          Pmsg3(000, _("Socket open error. proto=%d port=%d. ERR=%s\n"),
596             ipaddr->get_family(), ipaddr->get_port_host_order(), be.strerror());
597          continue;
598       }
599       /*
600        * Keep socket from timing out from inactivity
601        */
602       if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
603          berrno be;
604          Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
605                be.strerror());
606       }
607       /* connect to server */
608       if (connect(sockfd, ipaddr->get_sockaddr(), ipaddr->get_sockaddr_len()) < 0) {
609          save_errno = errno;
610          socketClose(sockfd);
611          continue;
612       }
613       *fatal = 0;
614       connected = true;
615       break;
616    }
617
618    if (!connected) {
619       free_addresses(addr_list);
620       errno = save_errno;
621       return NULL;
622    }
623    /*
624     * Keep socket from timing out from inactivity
625     *   Do this a second time out of paranoia
626     */
627    if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
628       berrno be;
629       Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
630             be.strerror());
631    }
632    BSOCK* ret =  init_bsock(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
633    free_addresses(addr_list);
634    return ret;
635 }
636
637 /*
638  * Try to connect to host for max_retry_time at retry_time intervals.
639  */
640 BSOCK *bnet_connect(JCR * jcr, int retry_interval, utime_t max_retry_time,
641                     const char *name, char *host, char *service, int port,
642                     int verbose)
643 {
644    int i;
645    BSOCK *bsock;
646    int fatal = 0;
647    time_t begin_time = time(NULL);
648    time_t now;
649
650    for (i = 0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL;
651         i -= retry_interval) {
652       berrno be;
653       if (fatal || (jcr && job_canceled(jcr))) {
654          return NULL;
655       }
656       Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
657             name, host, port, be.strerror());
658       if (i < 0) {
659          i = 60 * 5;               /* complain again in 5 minutes */
660          if (verbose)
661             Qmsg4(jcr, M_WARNING, 0, _(
662                "Could not connect to %s on %s:%d. ERR=%s\n"
663                "Retrying ...\n"), name, host, port, be.strerror());
664       }
665       bmicrosleep(retry_interval, 0);
666       now = time(NULL);
667       if (begin_time + max_retry_time <= now) {
668          Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
669                name, host, port, be.strerror());
670          return NULL;
671       }
672    }
673    return bsock;
674 }
675
676
677 /*
678  * Return the string for the error that occurred
679  * on the socket. Only the first error is retained.
680  */
681 const char *bnet_strerror(BSOCK * bsock)
682 {
683    berrno be;
684    if (bsock->errmsg == NULL) {
685       bsock->errmsg = get_pool_memory(PM_MESSAGE);
686    }
687    pm_strcpy(bsock->errmsg, be.strerror(bsock->b_errno));
688    return bsock->errmsg;
689 }
690
691 /*
692  * Format and send a message
693  *  Returns: false on error
694  *           true  on success
695  */
696 bool bnet_fsend(BSOCK * bs, const char *fmt, ...)
697 {
698    va_list arg_ptr;
699    int maxlen;
700
701    if (bs->errors || bs->terminated) {
702       return false;
703    }
704    /* This probably won't work, but we vsnprintf, then if we
705     * get a negative length or a length greater than our buffer
706     * (depending on which library is used), the printf was truncated, so
707     * get a bigger buffer and try again.
708     */
709    for (;;) {
710       maxlen = sizeof_pool_memory(bs->msg) - 1;
711       va_start(arg_ptr, fmt);
712       bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
713       va_end(arg_ptr);
714       if (bs->msglen > 0 && bs->msglen < (maxlen - 5)) {
715          break;
716       }
717       bs->msg = realloc_pool_memory(bs->msg, maxlen + maxlen / 2);
718    }
719    return bs->send();
720 // return bnet_send(bs);
721 }
722
723 int bnet_get_peer(BSOCK *bs, char *buf, socklen_t buflen) {
724 #if !defined(HAVE_WIN32)
725     if (bs->peer_addr.sin_family == 0) {
726         socklen_t salen = sizeof(bs->peer_addr);
727         int rval = (getpeername)(bs->fd, (struct sockaddr *)&bs->peer_addr, &salen);
728         if (rval < 0) return rval;
729     }
730     if (!inet_ntop(bs->peer_addr.sin_family, &bs->peer_addr.sin_addr, buf, buflen))
731         return -1;
732
733     return 0;
734 #else
735     return -1;
736 #endif
737 }
738 /*
739  * Set the network buffer size, suggested size is in size.
740  *  Actual size obtained is returned in bs->msglen
741  *
742  *  Returns: 0 on failure
743  *           1 on success
744  */
745 bool bnet_set_buffer_size(BSOCK * bs, uint32_t size, int rw)
746 {
747    uint32_t dbuf_size, start_size;
748 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
749    int opt;
750
751    opt = IPTOS_THROUGHPUT;
752    setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t) & opt, sizeof(opt));
753 #endif
754
755    if (size != 0) {
756       dbuf_size = size;
757    } else {
758       dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
759    }
760    start_size = dbuf_size;
761    if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size + 100)) == NULL) {
762       Qmsg0(bs->jcr(), M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
763       return false;
764    }
765    if (rw & BNET_SETBUF_READ) {
766       while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
767               SO_RCVBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
768          berrno be;
769          Qmsg1(bs->jcr(), M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
770          dbuf_size -= TAPE_BSIZE;
771       }
772       Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
773       if (dbuf_size != start_size) {
774          Qmsg1(bs->jcr(), M_WARNING, 0,
775                _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
776       }
777       if (dbuf_size % TAPE_BSIZE != 0) {
778          Qmsg1(bs->jcr(), M_ABORT, 0,
779                _("Network buffer size %d not multiple of tape block size.\n"),
780                dbuf_size);
781       }
782    }
783    if (size != 0) {
784       dbuf_size = size;
785    } else {
786       dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
787    }
788    start_size = dbuf_size;
789    if (rw & BNET_SETBUF_WRITE) {
790       while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
791               SO_SNDBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
792          berrno be;
793          Qmsg1(bs->jcr(), M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
794          dbuf_size -= TAPE_BSIZE;
795       }
796       Dmsg1(900, "set network buffer size=%d\n", dbuf_size);
797       if (dbuf_size != start_size) {
798          Qmsg1(bs->jcr(), M_WARNING, 0,
799                _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
800       }
801       if (dbuf_size % TAPE_BSIZE != 0) {
802          Qmsg1(bs->jcr(), M_ABORT, 0,
803                _("Network buffer size %d not multiple of tape block size.\n"),
804                dbuf_size);
805       }
806    }
807
808    bs->msglen = dbuf_size;
809    return true;
810 }
811
812 /*
813  * Set socket non-blocking
814  * Returns previous socket flag
815  */
816 int bnet_set_nonblocking (BSOCK *bsock) {
817 #ifndef HAVE_WIN32
818    int oflags;
819
820    /* Get current flags */
821    if ((oflags = fcntl(bsock->fd, F_GETFL, 0)) < 0) {
822       berrno be;
823       Jmsg1(bsock->jcr(), M_ABORT, 0, _("fcntl F_GETFL error. ERR=%s\n"), be.strerror());
824    }
825
826    /* Set O_NONBLOCK flag */
827    if ((fcntl(bsock->fd, F_SETFL, oflags|O_NONBLOCK)) < 0) {
828       berrno be;
829       Jmsg1(bsock->jcr(), M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.strerror());
830    }
831
832    bsock->blocking = 0;
833    return oflags;
834 #else
835    int flags;
836    u_long ioctlArg = 1;
837
838    flags = bsock->blocking;
839    ioctlsocket(bsock->fd, FIONBIO, &ioctlArg);
840    bsock->blocking = 0;
841
842    return flags;
843 #endif
844 }
845
846 /*
847  * Set socket blocking
848  * Returns previous socket flags
849  */
850 int bnet_set_blocking (BSOCK *bsock) 
851 {
852 #ifndef HAVE_WIN32
853    int oflags;
854    /* Get current flags */
855    if ((oflags = fcntl(bsock->fd, F_GETFL, 0)) < 0) {
856       berrno be;
857       Jmsg1(bsock->jcr(), M_ABORT, 0, _("fcntl F_GETFL error. ERR=%s\n"), be.strerror());
858    }
859
860    /* Set O_NONBLOCK flag */
861    if ((fcntl(bsock->fd, F_SETFL, oflags & ~O_NONBLOCK)) < 0) {
862       berrno be;
863       Jmsg1(bsock->jcr(), M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.strerror());
864    }
865
866    bsock->blocking = 1;
867    return oflags;
868 #else
869    int flags;
870    u_long ioctlArg = 0;
871
872    flags = bsock->blocking;
873    ioctlsocket(bsock->fd, FIONBIO, &ioctlArg);
874    bsock->blocking = 1;
875
876    return flags;
877 #endif
878 }
879
880 /*
881  * Restores socket flags
882  */
883 void bnet_restore_blocking (BSOCK *bsock, int flags) 
884 {
885 #ifndef HAVE_WIN32
886    if ((fcntl(bsock->fd, F_SETFL, flags)) < 0) {
887       berrno be;
888       Jmsg1(bsock->jcr(), M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.strerror());
889    }
890
891    bsock->blocking = (flags & O_NONBLOCK);
892 #else
893    u_long ioctlArg = flags;
894
895    ioctlsocket(bsock->fd, FIONBIO, &ioctlArg);
896    bsock->blocking = 1;
897 #endif
898 }
899
900
901 /*
902  * Send a network "signal" to the other end
903  *  This consists of sending a negative packet length
904  *
905  *  Returns: false on failure
906  *           true  on success
907  */
908 bool bnet_sig(BSOCK * bs, int signal)
909 {
910    return bs->signal(signal);
911 }
912
913 /*
914  * Convert a network "signal" code into
915  * human readable ASCII.
916  */
917 const char *bnet_sig_to_ascii(BSOCK * bs)
918 {
919    static char buf[30];
920    switch (bs->msglen) {
921    case BNET_EOD:
922       return "BNET_EOD";           /* end of data stream */
923    case BNET_EOD_POLL:
924       return "BNET_EOD_POLL";
925    case BNET_STATUS:
926       return "BNET_STATUS";
927    case BNET_TERMINATE:
928       return "BNET_TERMINATE";     /* terminate connection */
929    case BNET_POLL:
930       return "BNET_POLL";
931    case BNET_HEARTBEAT:
932       return "BNET_HEARTBEAT";
933    case BNET_HB_RESPONSE:
934       return "BNET_HB_RESPONSE";
935    case BNET_PROMPT:
936       return "BNET_PROMPT";
937    default:
938       sprintf(buf, _("Unknown sig %d"), (int)bs->msglen);
939       return buf;
940    }
941 }
942
943
944 /* Initialize internal socket structure.
945  *  This probably should be done in net_open
946  */
947 BSOCK *init_bsock(JCR * jcr, int sockfd, const char *who, const char *host, int port,
948                   struct sockaddr *client_addr)
949 {
950    Dmsg3(100, "who=%s host=%s port=%d\n", who, host, port);
951    BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
952    memset(bsock, 0, sizeof(BSOCK));
953    bsock->fd = sockfd;
954    bsock->tls = NULL;
955    bsock->errors = 0;
956    bsock->blocking = 1;
957    bsock->msg = get_pool_memory(PM_MESSAGE);
958    bsock->errmsg = get_pool_memory(PM_MESSAGE);
959    bsock->set_who(bstrdup(who));
960    bsock->set_host(bstrdup(host));
961    bsock->set_port(port);
962    memset(&bsock->peer_addr, 0, sizeof(bsock->peer_addr));
963    memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
964    /*
965     * ****FIXME**** reduce this to a few hours once
966     *   heartbeats are implemented
967     */
968    bsock->timeout = 60 * 60 * 6 * 24;   /* 6 days timeout */
969    bsock->set_jcr(jcr);
970    return bsock;
971 }
972
973 BSOCK *dup_bsock(BSOCK * osock)
974 {
975    BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
976    memcpy(bsock, osock, sizeof(BSOCK));
977    bsock->msg = get_pool_memory(PM_MESSAGE);
978    bsock->errmsg = get_pool_memory(PM_MESSAGE);
979    if (osock->who()) {
980       bsock->set_who(bstrdup(osock->who()));
981    }
982    if (osock->host()) {
983       bsock->set_host(bstrdup(osock->host()));
984    }
985    bsock->duped = true;
986    return bsock;
987 }
988
989 /* Close the network connection */
990 void bnet_close(BSOCK * bsock)
991 {
992    bsock->close();                    /* this calls destroy */
993 }
994
995 void term_bsock(BSOCK * bsock)
996 {
997    bsock->destroy();
998 }