1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2007-2011 Free Software Foundation Europe e.V.
5    Copyright (C) 2013-2018 Bareos GmbH & Co. KG
6 
7    This program is Free Software; you can redistribute it and/or
8    modify it under the terms of version three of the GNU Affero General Public
9    License as published by the Free Software Foundation and included
10    in the file LICENSE.
11 
12    This program is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15    Affero General Public License for more details.
16 
17    You should have received a copy of the GNU Affero General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20    02110-1301, USA.
21 */
22 /*
23  * TCP Sockets abstraction.
24  *
25  * Kern Sibbald
26  *
27  * Extracted from other source files by Marco van Wieringen, September 2013.
28  */
29 
30 #include "include/bareos.h"
31 #include "include/jcr.h"
32 #include <netdb.h>
33 #include <netinet/tcp.h>
34 #include "lib/bnet.h"
35 #include "lib/bpoll.h"
36 #include "lib/btimers.h"
37 #include "lib/tls_openssl.h"
38 
39 #ifndef ENODATA                    /* not defined on BSD systems */
40 #define ENODATA EPIPE
41 #endif
42 
43 #ifndef SOL_TCP
44 #define SOL_TCP IPPROTO_TCP
45 #endif
46 
47 #ifdef HAVE_WIN32
48 #define socketRead(fd, buf, len)  ::recv(fd, buf, len, 0)
49 #define socketWrite(fd, buf, len) ::send(fd, buf, len, 0)
50 #define socketClose(fd)           ::closesocket(fd)
51 #else
52 #define socketRead(fd, buf, len)  ::read(fd, buf, len)
53 #define socketWrite(fd, buf, len) ::write(fd, buf, len)
54 #define socketClose(fd)           ::close(fd)
55 #endif
56 
BareosSocketTCP()57 BareosSocketTCP::BareosSocketTCP() : BareosSocket()
58 {
59 }
60 
~BareosSocketTCP()61 BareosSocketTCP::~BareosSocketTCP()
62 {
63    destroy();
64 }
65 
clone()66 BareosSocket *BareosSocketTCP::clone()
67 {
68    BareosSocketTCP *clone = New(BareosSocketTCP(*this));
69 
70    /* do not use memory buffer from copied socket */
71    clone->msg = GetPoolMemory(PM_BSOCK);
72    clone->errmsg = GetPoolMemory(PM_MESSAGE);
73 
74    if (src_addr) {
75       src_addr = New(IPADDR(*(src_addr)));
76    }
77    if (who_) {
78       who_ = bstrdup(who_);
79    }
80    if (host_) {
81       host_ = bstrdup(host_);
82    }
83 
84    /* duplicate file descriptors */
85    if (fd_ >= 0) {
86       clone->fd_ = dup(fd_);
87    }
88    if (spool_fd_ >= 0) {
89       clone->spool_fd_ = dup(spool_fd_);
90    }
91 
92    clone->cloned_ = true;
93 
94    return clone;
95 }
96 
97 /*
98  * Try to connect to host for max_retry_time at retry_time intervals.
99  * Note, you must have called the constructor prior to calling
100  * this routine.
101  */
connect(JobControlRecord * jcr,int retry_interval,utime_t max_retry_time,utime_t heart_beat,const char * name,const char * host,char * service,int port,bool verbose)102 bool BareosSocketTCP::connect(JobControlRecord * jcr, int retry_interval, utime_t max_retry_time,
103                         utime_t heart_beat, const char *name, const char *host,
104                         char *service, int port, bool verbose)
105 {
106    bool ok = false;
107    int i;
108    int fatal = 0;
109    time_t begin_time = time(NULL);
110    time_t now;
111    btimer_t *tid = NULL;
112 
113    /*
114     * Try to trap out of OS call when time expires
115     */
116    if (max_retry_time) {
117       tid = start_thread_timer(jcr, pthread_self(), (uint32_t)max_retry_time);
118    }
119 
120    for (i = 0; !open(jcr, name, host, service, port, heart_beat, &fatal);
121         i -= retry_interval) {
122       BErrNo be;
123       if (fatal || (jcr && JobCanceled(jcr))) {
124          goto bail_out;
125       }
126       Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
127             name, host, port, be.bstrerror());
128       if (i < 0) {
129          i = 60 * 5;               /* complain again in 5 minutes */
130          if (verbose)
131             Qmsg4(jcr, M_WARNING, 0, _(
132                "Could not connect to %s on %s:%d. ERR=%s\n"
133                "Retrying ...\n"), name, host, port, be.bstrerror());
134       }
135       Bmicrosleep(retry_interval, 0);
136       now = time(NULL);
137       if (begin_time + max_retry_time <= now) {
138          Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
139                name, host, port, be.bstrerror());
140          goto bail_out;
141       }
142    }
143    ok = true;
144 
145 bail_out:
146    if (tid) {
147       StopThreadTimer(tid);
148    }
149    return ok;
150 }
151 
152 /*
153  * Finish initialization of the pocket structure.
154  */
FinInit(JobControlRecord * jcr,int sockfd,const char * who,const char * host,int port,struct sockaddr * lclient_addr)155 void BareosSocketTCP::FinInit(JobControlRecord * jcr, int sockfd, const char *who, const char *host,
156                          int port, struct sockaddr *lclient_addr)
157 {
158    Dmsg3(100, "who=%s host=%s port=%d\n", who, host, port);
159    SetWho(bstrdup(who));
160    SetHost(bstrdup(host));
161    SetPort(port);
162    memcpy(&client_addr, lclient_addr, sizeof(client_addr));
163    SetJcr(jcr);
164 }
165 
166 /*
167  * Open a TCP connection to the server
168  *
169  * Returns NULL
170  * Returns BareosSocket * pointer on success
171  */
open(JobControlRecord * jcr,const char * name,const char * host,char * service,int port,utime_t heart_beat,int * fatal)172 bool BareosSocketTCP::open(JobControlRecord *jcr, const char *name, const char *host, char *service,
173                      int port, utime_t heart_beat, int *fatal)
174 {
175    int sockfd = -1;
176    dlist *addr_list;
177    IPADDR *ipaddr, *next, *to_free;
178    bool connected = false;
179    int value;
180    const char *errstr;
181    int save_errno = 0;
182 
183    /*
184     * Fill in the structure serv_addr with the address of
185     * the server that we want to connect with.
186     */
187    if ((addr_list = BnetHost2IpAddrs(host, 0, &errstr)) == NULL) {
188       /*
189        * Note errstr is not malloc'ed
190        */
191       Qmsg2(jcr, M_ERROR, 0, _("BnetHost2IpAddrs() for host \"%s\" failed: ERR=%s\n"),
192             host, errstr);
193       Dmsg2(100, "BnetHost2IpAddrs() for host %s failed: ERR=%s\n",
194             host, errstr);
195       *fatal = 1;
196       return false;
197    }
198 
199    /*
200     * Remove any duplicate addresses.
201     */
202    for (ipaddr = (IPADDR *)addr_list->first();
203         ipaddr;
204         ipaddr = (IPADDR *)addr_list->next(ipaddr)) {
205       next = (IPADDR *)addr_list->next(ipaddr);
206       while (next) {
207          /*
208           * See if the addresses match.
209           */
210          if (ipaddr->GetSockaddrLen() == next->GetSockaddrLen() &&
211              memcmp(ipaddr->get_sockaddr(), next->get_sockaddr(),
212                     ipaddr->GetSockaddrLen()) == 0) {
213             to_free = next;
214             next = (IPADDR *)addr_list->next(next);
215             addr_list->remove(to_free);
216             delete to_free;
217          } else {
218             next = (IPADDR *)addr_list->next(next);
219          }
220       }
221    }
222 
223    if (use_keepalive_) {
224       value = 1;
225    } else {
226       value = 0;
227    }
228 
229    foreach_dlist(ipaddr, addr_list) {
230       ipaddr->SetPortNet(htons(port));
231       char allbuf[256 * 10];
232       char curbuf[256];
233       Dmsg2(100, "Current %s All %s\n",
234                    ipaddr->build_address_str(curbuf, sizeof(curbuf)),
235                    BuildAddressesString(addr_list, allbuf, sizeof(allbuf)));
236       /* Open a TCP socket */
237       if ((sockfd = socket(ipaddr->GetFamily(), SOCK_STREAM, 0)) < 0) {
238          BErrNo be;
239          save_errno = errno;
240          switch (errno) {
241 #ifdef EPFNOSUPPORT
242          case EPFNOSUPPORT:
243             /*
244              * The name lookup of the host returned an address in a protocol family
245              * we don't support. Suppress the error and try the next address.
246              */
247             break;
248 #endif
249 #ifdef EAFNOSUPPORT
250          case EAFNOSUPPORT:
251             /*
252              * The name lookup of the host returned an address in a address family
253              * we don't support. Suppress the error and try the next address.
254              */
255             break;
256 #endif
257          default:
258             *fatal = 1;
259             Pmsg3(000, _("Socket open error. proto=%d port=%d. ERR=%s\n"),
260                ipaddr->GetFamily(), ipaddr->GetPortHostOrder(), be.bstrerror());
261             break;
262          }
263          continue;
264       }
265 
266       /*
267        * Bind to the source address if it is set
268        */
269       if (src_addr) {
270          if (bind(sockfd, src_addr->get_sockaddr(), src_addr->GetSockaddrLen()) < 0) {
271             BErrNo be;
272             save_errno = errno;
273             *fatal = 1;
274             Pmsg2(000, _("Source address bind error. proto=%d. ERR=%s\n"),
275                   src_addr->GetFamily(), be.bstrerror() );
276             if (sockfd >= 0) {
277                socketClose(sockfd);
278                sockfd = -1;
279             }
280             continue;
281          }
282       }
283 
284       /*
285        * Keep socket from timing out from inactivity
286        */
287       SetKeepalive(jcr, sockfd, use_keepalive_, heart_beat, heart_beat);
288 
289       /*
290        * Connect to server
291        */
292       if (::connect(sockfd, ipaddr->get_sockaddr(), ipaddr->GetSockaddrLen()) < 0) {
293          save_errno = errno;
294          if (sockfd >= 0) {
295             socketClose(sockfd);
296             sockfd = -1;
297          }
298          continue;
299       }
300       *fatal = 0;
301       connected = true;
302       break;
303    }
304 
305    if (!connected) {
306       FreeAddresses(addr_list);
307       errno = save_errno | b_errno_win32;
308       if (sockfd >= 0) {
309          socketClose(sockfd);
310          sockfd = -1;
311       }
312       return false;
313    }
314 
315    /*
316     * Keep socket from timing out from inactivity
317     * Do this a second time out of paranoia
318     */
319    if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&value, sizeof(value)) < 0) {
320       BErrNo be;
321       Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"), be.bstrerror());
322    }
323 
324    FinInit(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
325    FreeAddresses(addr_list);
326    fd_ = sockfd;
327    return true;
328 }
329 
330 
SetKeepalive(JobControlRecord * jcr,int sockfd,bool enable,int keepalive_start,int keepalive_interval)331 bool BareosSocketTCP::SetKeepalive(JobControlRecord *jcr, int sockfd, bool enable, int keepalive_start, int keepalive_interval)
332 {
333    int value = int(enable);
334 
335    /*
336     * Keep socket from timing out from inactivity
337     */
338    if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&value, sizeof(value)) < 0) {
339       BErrNo be;
340       Qmsg1(jcr, M_WARNING, 0, _("Failed to set SO_KEEPALIVE on socket: %s\n"), be.bstrerror());
341       return false;
342    }
343 
344    if (enable && keepalive_interval) {
345 #ifdef HAVE_WIN32
346       struct s_tcp_keepalive {
347          u_long  onoff;
348          u_long  keepalivetime;
349          u_long  keepaliveinterval;
350       } val;
351       val.onoff = enable;
352       val.keepalivetime = keepalive_start*1000L;
353       val.keepaliveinterval = keepalive_interval*1000L;
354       DWORD got = 0;
355       if (WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, &val, sizeof(val), NULL, 0, &got, NULL, NULL) != 0) {
356          Qmsg1(jcr, M_WARNING, 0, "Failed to set SIO_KEEPALIVE_VALS on socket: %d\n", WSAGetLastError());
357          return false;
358       }
359 #else
360 #if defined(TCP_KEEPIDLE)
361       if (setsockopt(sockfd, SOL_TCP, TCP_KEEPIDLE, (sockopt_val_t)&keepalive_start, sizeof(keepalive_start)) < 0) {
362          BErrNo be;
363          Qmsg2(jcr, M_WARNING, 0, _("Failed to set TCP_KEEPIDLE = %d on socket: %s\n"),
364                keepalive_start, be.bstrerror());
365          return false;
366       }
367       if (setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, (sockopt_val_t)&keepalive_interval, sizeof(keepalive_interval)) < 0) {
368          BErrNo be;
369          Qmsg2(jcr, M_WARNING, 0, _("Failed to set TCP_KEEPINTVL = %d on socket: %s\n"),
370                keepalive_interval, be.bstrerror());
371          return false;
372       }
373 #endif
374 #endif
375    }
376    return true;
377 }
378 
379 
SendPacket(int32_t * hdr,int32_t pktsiz)380 bool BareosSocketTCP::SendPacket(int32_t *hdr, int32_t pktsiz)
381 {
382    Enter(400);
383 
384    int32_t rc;
385    bool ok = true;
386 
387    out_msg_no++;            /* increment message number */
388 
389    /*
390     * Send data packet
391     */
392    timer_start = watchdog_time;  /* start timer */
393    ClearTimedOut();
394 
395    /*
396     * Full I/O done in one write
397     */
398    rc = write_nbytes((char *)hdr, pktsiz);
399    timer_start = 0;         /* clear timer */
400    if (rc != pktsiz) {
401       errors++;
402       if (errno == 0) {
403          b_errno = EIO;
404       } else {
405          b_errno = errno;
406       }
407       if (rc < 0) {
408          if (!suppress_error_msgs_) {
409             Qmsg5(jcr_, M_ERROR, 0,
410                   _("Write error sending %d bytes to %s:%s:%d: ERR=%s\n"),
411                   message_length, who_,
412                   host_, port_, this->bstrerror());
413          }
414       } else {
415          Qmsg5(jcr_, M_ERROR, 0,
416                _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
417                message_length, who_, host_, port_, rc);
418       }
419       ok = false;
420    }
421 
422    Leave(400);
423 
424    return ok;
425 }
426 
427 /*
428  * Send a message over the network. The send consists of
429  * two network packets. The first is sends a 32 bit integer containing
430  * the length of the data packet which follows.
431  *
432  * Returns: false on failure
433  *          true  on success
434  */
send()435 bool BareosSocketTCP::send()
436 {
437    /*
438     * Send msg (length: message_length).
439     * As send() and recv() uses the same buffer (msg and message_length)
440     * store the original message_length in an own variable,
441     * that will not be modifed by recv().
442     */
443    const int32_t o_msglen = message_length;
444    int32_t pktsiz;
445    int32_t written = 0;
446    int32_t packet_msglen = 0;
447    bool ok = true;
448    /*
449     * Store packet length at head of message -- note, we have reserved an int32_t just before msg,
450     * So we can store there
451     */
452    int32_t *hdr = (int32_t *)(msg - (int)header_length);
453 
454    if (errors) {
455       if (!suppress_error_msgs_) {
456          Qmsg4(jcr_, M_ERROR, 0,  _("Socket has errors=%d on call to %s:%s:%d\n"),
457              errors, who_, host_, port_);
458       }
459       return false;
460    }
461 
462    if (IsTerminated()) {
463       if (!suppress_error_msgs_) {
464          Qmsg4(jcr_, M_ERROR, 0,  _("Socket is terminated=%d on call to %s:%s:%d\n"),
465              IsTerminated(), who_, host_, port_);
466       }
467       return false;
468    }
469 
470    LockMutex();
471 
472    /*
473     * Compute total packet length
474     */
475    if (o_msglen <= 0) {
476       pktsiz = header_length;                /* signal, no data */
477       *hdr = htonl(o_msglen);                /* store signal */
478       ok = SendPacket(hdr, pktsiz);
479    } else {
480       /*
481        * msg might be to long for a single Bareos packet.
482        * If so, send msg as multiple packages.
483        */
484       while (ok && (written < o_msglen)) {
485          if ((o_msglen - written) > max_message_len) {
486             /*
487              * Message is to large for a single Bareos packet.
488              * Send it via multiple packets.
489              */
490             pktsiz = max_packet_size;                  /* header + data */
491             packet_msglen = max_message_len;
492          } else {
493             /*
494              * Remaining message fits into one Bareos packet
495              */
496             pktsiz = header_length + (o_msglen-written); /* header + data */
497             packet_msglen = (o_msglen-written);
498          }
499 
500          *hdr = htonl(packet_msglen);        /* store length */
501          ok = SendPacket(hdr, pktsiz);
502          written += packet_msglen;
503          hdr = (int32_t *)(msg + written - (int)header_length);
504       }
505    }
506 
507    UnlockMutex();
508 
509    return ok;
510 }
511 
512 /*
513  * Receive a message from the other end. Each message consists of
514  * two packets. The first is a header that contains the size
515  * of the data that follows in the second packet.
516  * Returns number of bytes read (may return zero)
517  * Returns -1 on signal (BNET_SIGNAL)
518  * Returns -2 on hard end of file (BNET_HARDEOF)
519  * Returns -3 on error  (BNET_ERROR)
520  *
521  *  Unfortunately, it is a bit complicated because we have these
522  *    four return types:
523  *    1. Normal data
524  *    2. Signal including end of data stream
525  *    3. Hard end of file
526  *    4. Error
527  *  Using IsBnetStop() and IsBnetError() you can figure this all out.
528  */
recv()529 int32_t BareosSocketTCP::recv()
530 {
531    int32_t nbytes;
532    int32_t pktsiz;
533 
534    msg[0] = 0;
535    message_length = 0;
536    if (errors || IsTerminated()) {
537       return BNET_HARDEOF;
538    }
539 
540    if (mutex_) {
541       mutex_->lock();
542    }
543 
544    read_seqno++;            /* bump sequence number */
545    timer_start = watchdog_time;  /* set start wait time */
546    ClearTimedOut();
547 
548    /*
549     * Get data size -- in int32_t
550     */
551    if ((nbytes = read_nbytes((char *)&pktsiz, header_length)) <= 0) {
552       timer_start = 0;      /* clear timer */
553       /*
554        * Probably pipe broken because client died
555        */
556       if (errno == 0) {
557          b_errno = ENODATA;
558       } else {
559          b_errno = errno;
560       }
561       errors++;
562       nbytes = BNET_HARDEOF;        /* assume hard EOF received */
563       goto get_out;
564    }
565    timer_start = 0;         /* clear timer */
566    if (nbytes != header_length) {
567       errors++;
568       b_errno = EIO;
569       Qmsg5(jcr_, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
570             header_length, nbytes, who_, host_, port_);
571       nbytes = BNET_ERROR;
572       goto get_out;
573    }
574 
575    pktsiz = ntohl(pktsiz);         /* decode no. of bytes that follow */
576 
577    if (pktsiz == 0) {              /* No data transferred */
578       timer_start = 0;             /* clear timer */
579       in_msg_no++;
580       message_length = 0;
581       nbytes = 0;                  /* zero bytes read */
582       goto get_out;
583    }
584 
585    /*
586     * If signal or packet size too big
587     */
588    if (pktsiz < 0 || pktsiz > max_packet_size) {
589       if (pktsiz > 0) {            /* if packet too big */
590          Qmsg3(jcr_, M_FATAL, 0,
591                _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
592                who_, host_, port_);
593          pktsiz = BNET_TERMINATE;  /* hang up */
594       }
595       if (pktsiz == BNET_TERMINATE) {
596          SetTerminated();
597       }
598       timer_start = 0;                /* clear timer */
599       b_errno = ENODATA;
600       message_length = pktsiz;                /* signal code */
601       nbytes =  BNET_SIGNAL;          /* signal */
602       goto get_out;
603    }
604 
605    /*
606     * Make sure the buffer is big enough + one byte for EOS
607     */
608    if (pktsiz >= (int32_t) SizeofPoolMemory(msg)) {
609       msg = ReallocPoolMemory(msg, pktsiz + 100);
610    }
611 
612    timer_start = watchdog_time;  /* set start wait time */
613    ClearTimedOut();
614 
615    /*
616     * Now read the actual data
617     */
618    if ((nbytes = read_nbytes(msg, pktsiz)) <= 0) {
619       timer_start = 0;      /* clear timer */
620       if (errno == 0) {
621          b_errno = ENODATA;
622       } else {
623          b_errno = errno;
624       }
625       errors++;
626       Qmsg4(jcr_, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
627             who_, host_, port_, this->bstrerror());
628       nbytes = BNET_ERROR;
629       goto get_out;
630    }
631    timer_start = 0;         /* clear timer */
632    in_msg_no++;
633    message_length = nbytes;
634    if (nbytes != pktsiz) {
635       b_errno = EIO;
636       errors++;
637       Qmsg5(jcr_, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
638             pktsiz, nbytes, who_, host_, port_);
639       nbytes = BNET_ERROR;
640       goto get_out;
641    }
642 
643    /*
644     * Always add a zero by to properly Terminate any string that was send to us.
645     * Note, we ensured above that the buffer is at least one byte longer than
646     * the message length.
647     */
648    msg[nbytes] = 0; /* Terminate in case it is a string */
649 
650    /*
651     * The following uses *lots* of resources so turn it on only for serious debugging.
652     */
653    Dsm_check(300);
654 
655 get_out:
656    if (mutex_) {
657       mutex_->unlock();
658    }
659 
660    return nbytes;                  /* return actual length of message */
661 }
662 
GetPeer(char * buf,socklen_t buflen)663 int BareosSocketTCP::GetPeer(char *buf, socklen_t buflen)
664 {
665 #if !defined(HAVE_WIN32)
666     if (peer_addr.sin_family == 0) {
667         socklen_t salen = sizeof(peer_addr);
668         int rval = (getpeername)(fd_, (struct sockaddr *)&peer_addr, &salen);
669         if (rval < 0) return rval;
670     }
671     if (!inet_ntop(peer_addr.sin_family, &peer_addr.sin_addr, buf, buflen))
672         return -1;
673 
674     return 0;
675 #else
676     return -1;
677 #endif
678 }
679 
680 /*
681  * Set the network buffer size, suggested size is in size.
682  * Actual size obtained is returned in bs->message_length
683  *
684  * Returns: false on failure
685  *          true  on success
686  */
SetBufferSize(uint32_t size,int rw)687 bool BareosSocketTCP::SetBufferSize(uint32_t size, int rw)
688 {
689    uint32_t dbuf_size, start_size;
690 
691 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
692    int opt;
693 
694    opt = IPTOS_THROUGHPUT;
695    setsockopt(fd_, IPPROTO_IP, IP_TOS, (sockopt_val_t)&opt, sizeof(opt));
696 #endif
697 
698    if (size != 0) {
699       dbuf_size = size;
700    } else {
701       dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
702    }
703    start_size = dbuf_size;
704    if ((msg = ReallocPoolMemory(msg, dbuf_size + 100)) == NULL) {
705       Qmsg0(get_jcr(), M_FATAL, 0, _("Could not malloc BareosSocket data buffer\n"));
706       return false;
707    }
708 
709    /*
710     * If user has not set the size, use the OS default -- i.e. do not
711     * try to set it.  This allows sys admins to set the size they
712     * want in the OS, and BAREOS will comply. See bug #1493
713     */
714    if (size == 0) {
715       message_length = dbuf_size;
716       return true;
717    }
718 
719    if (rw & BNET_SETBUF_READ) {
720       while ((dbuf_size > TAPE_BSIZE) && (setsockopt(fd_, SOL_SOCKET,
721               SO_RCVBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
722          BErrNo be;
723          Qmsg1(get_jcr(), M_ERROR, 0, _("sockopt error: %s\n"), be.bstrerror());
724          dbuf_size -= TAPE_BSIZE;
725       }
726       Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
727       if (dbuf_size != start_size) {
728          Qmsg1(get_jcr(), M_WARNING, 0,
729                _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
730       }
731    }
732    if (size != 0) {
733       dbuf_size = size;
734    } else {
735       dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
736    }
737    start_size = dbuf_size;
738    if (rw & BNET_SETBUF_WRITE) {
739       while ((dbuf_size > TAPE_BSIZE) && (setsockopt(fd_, SOL_SOCKET,
740               SO_SNDBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
741          BErrNo be;
742          Qmsg1(get_jcr(), M_ERROR, 0, _("sockopt error: %s\n"), be.bstrerror());
743          dbuf_size -= TAPE_BSIZE;
744       }
745       Dmsg1(900, "set network buffer size=%d\n", dbuf_size);
746       if (dbuf_size != start_size) {
747          Qmsg1(get_jcr(), M_WARNING, 0,
748                _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
749       }
750    }
751 
752    message_length = dbuf_size;
753    return true;
754 }
755 
756 /*
757  * Set socket non-blocking
758  *
759  * Returns previous socket flag
760  */
SetNonblocking()761 int BareosSocketTCP::SetNonblocking()
762 {
763 #ifndef HAVE_WIN32
764    int oflags;
765 
766    /*
767     * Get current flags
768     */
769    if ((oflags = fcntl(fd_, F_GETFL, 0)) < 0) {
770       BErrNo be;
771       Qmsg1(get_jcr(), M_ABORT, 0, _("fcntl F_GETFL error. ERR=%s\n"), be.bstrerror());
772    }
773 
774    /*
775     * Set O_NONBLOCK flag
776     */
777    if ((fcntl(fd_, F_SETFL, oflags|O_NONBLOCK)) < 0) {
778       BErrNo be;
779       Qmsg1(get_jcr(), M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.bstrerror());
780    }
781 
782    blocking_ = 0;
783    return oflags;
784 #else
785    int flags;
786    u_long ioctlArg = 1;
787 
788    flags = blocking_;
789    ioctlsocket(fd_, FIONBIO, &ioctlArg);
790    blocking_ = 0;
791 
792    return flags;
793 #endif
794 }
795 
796 /*
797  * Set socket blocking
798  *
799  * Returns previous socket flags
800  */
SetBlocking()801 int BareosSocketTCP::SetBlocking()
802 {
803 #ifndef HAVE_WIN32
804    int oflags;
805 
806    /*
807     * Get current flags
808     */
809    if ((oflags = fcntl(fd_, F_GETFL, 0)) < 0) {
810       BErrNo be;
811       Qmsg1(get_jcr(), M_ABORT, 0, _("fcntl F_GETFL error. ERR=%s\n"), be.bstrerror());
812    }
813 
814    /*
815     * Set O_NONBLOCK flag
816     */
817    if ((fcntl(fd_, F_SETFL, oflags & ~O_NONBLOCK)) < 0) {
818       BErrNo be;
819       Qmsg1(get_jcr(), M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.bstrerror());
820    }
821 
822    blocking_ = 1;
823    return oflags;
824 #else
825    int flags;
826    u_long ioctlArg = 0;
827 
828    flags = blocking_;
829    ioctlsocket(fd_, FIONBIO, &ioctlArg);
830    blocking_ = 1;
831 
832    return flags;
833 #endif
834 }
835 
836 /*
837  * Restores socket flags
838  */
RestoreBlocking(int flags)839 void BareosSocketTCP::RestoreBlocking(int flags)
840 {
841 #ifndef HAVE_WIN32
842    if ((fcntl(fd_, F_SETFL, flags)) < 0) {
843       BErrNo be;
844       Qmsg1(get_jcr(), M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.bstrerror());
845    }
846 
847    blocking_ = (flags & O_NONBLOCK) ? true : false;
848 #else
849    u_long ioctlArg = flags;
850 
851    ioctlsocket(fd_, FIONBIO, &ioctlArg);
852    blocking_ = 1;
853 #endif
854 }
855 
856 /*
857  * Wait for a specified time for data to appear on
858  * the BareosSocket connection.
859  *
860  * Returns: 1 if data available
861  *          0 if timeout
862  *         -1 if error
863  */
WaitData(int sec,int usec)864 int BareosSocketTCP::WaitData(int sec, int usec)
865 {
866    int msec;
867 
868    msec = (sec * 1000) + (usec / 1000);
869    switch (WaitForReadableFd(fd_, msec, true)) {
870    case 0:
871       b_errno = 0;
872       return 0;
873    case -1:
874       b_errno = errno;
875       return -1;                /* error return */
876    default:
877       b_errno = 0;
878       return 1;
879    }
880 }
881 
882 /*
883  * As above, but returns on interrupt
884  */
WaitDataIntr(int sec,int usec)885 int BareosSocketTCP::WaitDataIntr(int sec, int usec)
886 {
887    int msec;
888 
889    msec = (sec * 1000) + (usec / 1000);
890    switch (WaitForReadableFd(fd_, msec, false)) {
891    case 0:
892       b_errno = 0;
893       return 0;
894    case -1:
895       b_errno = errno;
896       return -1;                /* error return */
897    default:
898       b_errno = 0;
899       return 1;
900    }
901 }
902 
903 #ifndef SHUT_RDWR
904 #define SHUT_RDWR 2
905 #endif
906 
close()907 void BareosSocketTCP::close()
908 {
909    /* if not cloned */
910    ClearLocking();
911    CloseTlsConnectionAndFreeMemory();
912 
913    if (fd_ >= 0) {
914       if (!cloned_) {
915          if (IsTimedOut()) {
916             shutdown(fd_, SHUT_RDWR);
917          }
918       }
919       socketClose(fd_);
920       fd_ = -1;
921    }
922 }
923 
destroy()924 void BareosSocketTCP::destroy()
925 {
926    /* if this object is cloned
927     * some memory or file descriptors
928     * are duplicated not just copied */
929 
930    if (msg) { /* duplicated */
931       FreePoolMemory(msg);
932       msg = nullptr;
933    }
934    if (errmsg) { /* duplicated */
935       FreePoolMemory(errmsg);
936       errmsg = nullptr;
937    }
938    if (who_) { /* duplicated */
939       free(who_);
940       who_ = nullptr;
941    }
942    if (host_) { /* duplicated */
943       free(host_);
944       host_ = nullptr;
945    }
946    if (src_addr) { /* duplicated */
947       free(src_addr);
948       src_addr = nullptr;
949    }
950    if (fd_ >= 0) { /* duplicated */
951       socketClose(fd_);
952       fd_ = -1;
953    }
954    if(spool_fd_ >= 0) { /* duplicated */
955       socketClose(spool_fd_);
956       spool_fd_ = -1;
957    }
958 }
959 
960 /*
961  * Read a nbytes from the network.
962  * It is possible that the total bytes require in several
963  * read requests
964  */
read_nbytes(char * ptr,int32_t nbytes)965 int32_t BareosSocketTCP::read_nbytes(char *ptr, int32_t nbytes)
966 {
967    int32_t nleft, nread;
968 
969 #ifdef HAVE_TLS
970    if (tls_conn) {
971       return (tls_conn->TlsBsockReadn(this, ptr, nbytes));
972    }
973 #endif /* HAVE_TLS */
974 
975    nleft = nbytes;
976    while (nleft > 0) {
977       errno = 0;
978       nread = socketRead(fd_, ptr, nleft);
979       if (IsTimedOut() || IsTerminated()) {
980          return -1;
981       }
982 
983 #ifdef HAVE_WIN32
984       /*
985        * For Windows, we must simulate Unix errno on a socket error in order to handle errors correctly.
986        */
987       if (nread == SOCKET_ERROR) {
988         DWORD err = WSAGetLastError();
989         nread = -1;
990         if (err == WSAEINTR) {
991            errno = EINTR;
992         } else if (err == WSAEWOULDBLOCK) {
993            errno = EAGAIN;
994         } else {
995            errno = EIO;            /* some other error */
996         }
997      }
998 #endif
999 
1000       if (nread == -1) {
1001          if (errno == EINTR) {
1002             continue;
1003          }
1004          if (errno == EAGAIN) {
1005             Bmicrosleep(0, 20000); /* try again in 20ms */
1006             continue;
1007          }
1008       }
1009 
1010       if (nread <= 0) {
1011          return -1;                /* error, or EOF */
1012       }
1013 
1014       nleft -= nread;
1015       ptr += nread;
1016       if (UseBwlimit()) {
1017          ControlBwlimit(nread);
1018       }
1019    }
1020 
1021    return nbytes - nleft;          /* return >= 0 */
1022 }
1023 
1024 /*
1025  * Write nbytes to the network.
1026  * It may require several writes.
1027  */
write_nbytes(char * ptr,int32_t nbytes)1028 int32_t BareosSocketTCP::write_nbytes(char *ptr, int32_t nbytes)
1029 {
1030    int32_t nleft, nwritten;
1031 
1032    if (IsSpooling()) {
1033       nwritten = write(spool_fd_, ptr, nbytes);
1034       if (nwritten != nbytes) {
1035          BErrNo be;
1036          b_errno = errno;
1037          Qmsg1(jcr(), M_FATAL, 0, _("Attr spool write error. ERR=%s\n"), be.bstrerror());
1038          Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes);
1039          errno = b_errno;
1040          return -1;
1041       }
1042       return nbytes;
1043    }
1044 
1045 #ifdef HAVE_TLS
1046    if (tls_conn) {
1047       return (tls_conn->TlsBsockWriten(this, ptr, nbytes));
1048    }
1049 #endif /* HAVE_TLS */
1050 
1051    nleft = nbytes;
1052    while (nleft > 0) {
1053       do {
1054          errno = 0;
1055          nwritten = socketWrite(fd_, ptr, nleft);
1056          if (IsTimedOut() || IsTerminated()) {
1057             return -1;
1058          }
1059 
1060 #ifdef HAVE_WIN32
1061          /*
1062           * For Windows, we must simulate Unix errno on a socket
1063           *  error in order to handle errors correctly.
1064           */
1065          if (nwritten == SOCKET_ERROR) {
1066             DWORD err = WSAGetLastError();
1067             nwritten = -1;
1068             if (err == WSAEINTR) {
1069                errno = EINTR;
1070             } else if (err == WSAEWOULDBLOCK) {
1071                errno = EAGAIN;
1072             } else {
1073                errno = EIO;        /* some other error */
1074             }
1075          }
1076 #endif
1077 
1078       } while (nwritten == -1 && errno == EINTR);
1079 
1080       /*
1081        * If connection is non-blocking, we will get EAGAIN, so
1082        * use select()/poll() to keep from consuming all
1083        * the CPU and try again.
1084        */
1085       if (nwritten == -1 && errno == EAGAIN) {
1086          WaitForWritableFd(fd_, 1, false);
1087          continue;
1088       }
1089 
1090       if (nwritten <= 0) {
1091          return -1;                /* error */
1092       }
1093 
1094       nleft -= nwritten;
1095       ptr += nwritten;
1096       if (UseBwlimit()) {
1097          ControlBwlimit(nwritten);
1098       }
1099    }
1100 
1101    return nbytes - nleft;
1102 }
1103 
ConnectionReceivedTerminateSignal()1104 bool BareosSocketTCP::ConnectionReceivedTerminateSignal()
1105 {
1106   int32_t signal;
1107   SetNonblocking();
1108   bool terminated = false;
1109   if (::recv(fd_, (char*)&signal, 4, MSG_PEEK) == 4) {
1110     signal = ntohl(signal);
1111     if (signal == BNET_TERMINATE) {
1112        SetTerminated();
1113        terminated = true;
1114     }
1115   }
1116   SetBlocking();
1117   return terminated;
1118 }
1119