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