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