1 /*
2    Bacula(R) - The Network Backup Solution
3 
4    Copyright (C) 2000-2020 Kern Sibbald
5 
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8 
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13 
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16 
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  * Bacula Sock Class definition
21  *   Note, the old non-class code is in bnet.c, and the
22  *   new class code associated with this file is in bsock.c
23  *
24  * The new code inherit common functions from BSOCKCORE class
25  * and implement BSOCK/Bacula specific protocols and data flow.
26  *
27  * Kern Sibbald, May MM
28  *
29  * Major refactoring of BSOCK code written by:
30  *
31  * Radosław Korzeniewski, MMXVIII
32  * radoslaw@korzeniewski.net, radekk@inteos.pl
33  * Inteos Sp. z o.o. http://www.inteos.pl/
34  *
35  * Zero msglen from other end indicates soft eof (usually
36  *   end of some binary data stream, but not end of conversation).
37  *
38  * Negative msglen, is special "signal" (no data follows).
39  *   See below for SIGNAL codes.
40  */
41 
42 #ifndef __BSOCK_H_
43 #define __BSOCK_H_
44 
45 #define BSOCK_TIMEOUT  3600 * 24 * 200;  /* default 200 days */
46 
47 class BSOCK: public BSOCKCORE {
48 public:
49    FILE *m_spool_fd;                  /* spooling file */
50    POOLMEM *cmsg;                     /* Compress buffer */
51 
52 private:
53    boffset_t m_data_end;              /* offset of data written */
54    boffset_t m_last_data_end;         /* offset of last valid data written */
55    int32_t m_FileIndex;               /* attr spool FI */
56    int32_t m_lastFileIndex;           /* last valid attr spool FI */
57    int32_t m_lastFlushIndex;          /* Last FileIndex flushed */
58    bool m_spool: 1;                   /* set for spooling */
59    bool m_compress: 1;                /* set to use comm line compression */
60    uint64_t m_CommBytes;              /* Bytes sent */
61    uint64_t m_CommCompressedBytes;    /* Compressed bytes sent */
62 
63    bool open(JCR *jcr, const char *name, char *host, char *service,
64                int port, utime_t heart_beat, int *fatal);
65    void init();
66    void _destroy();
67    int32_t write_nbytes(char *ptr, int32_t nbytes);
68 
69 public:
70    BSOCK();
71    BSOCK(int sockfd);
72    ~BSOCK();
73   // int32_t recv(int /*len*/) { return recv(); };
74    int32_t recv();
send()75    bool send() { return send(0); };
76    bool send(int flags);
77    bool signal(int signal);
78    void close();              /* close connection and destroy packet */
79    bool comm_compress();               /* in bsock.c */
80    bool despool(void update_attr_spool_size(ssize_t size), ssize_t tsize);
81    bool authenticate_director(const char *name, const char *password,
82            TLS_CONTEXT *tls_ctx, char *response, int response_len);
83 
84    /* Inline functions */
is_spooling()85    bool is_spooling() const { return m_spool; };
can_compress()86    bool can_compress() const { return m_compress; };
set_data_end(int32_t FileIndex)87    void set_data_end(int32_t FileIndex) {
88           if (m_spool && FileIndex > m_FileIndex) {
89               m_lastFileIndex = m_FileIndex;
90               m_last_data_end = m_data_end;
91               m_FileIndex = FileIndex;
92               m_data_end = ftello(m_spool_fd);
93            }
94         };
set_lastFlushIndex(int32_t FlushIndex)95    void set_lastFlushIndex(int32_t FlushIndex) { m_lastFlushIndex = FlushIndex; };
get_last_data_end()96    boffset_t get_last_data_end() { return m_last_data_end; };
get_lastFileIndex()97    uint32_t get_lastFileIndex() { return m_lastFileIndex; };
get_lastFlushIndex()98    uint32_t get_lastFlushIndex() { return m_lastFlushIndex; };
CommBytes()99    uint32_t CommBytes() { return m_CommBytes; };
CommCompressedBytes()100    uint32_t CommCompressedBytes() { return m_CommCompressedBytes; };
set_spooling()101    void set_spooling() { m_spool = true; };
clear_spooling()102    void clear_spooling() { m_spool = false; };
set_compress()103    void set_compress() { m_compress = true; };
clear_compress()104    void clear_compress() { m_compress = false; };
105    void dump();
106 };
107 
108 /*
109  *  Signal definitions for use in bsock->signal()
110  *  Note! These must be negative.  There are signals that are generated
111  *   by the bsock software not by the OS ...
112  */
113 enum {
114    BNET_EOD            = -1,          /* End of data stream, new data may follow */
115    BNET_EOD_POLL       = -2,          /* End of data and poll all in one */
116    BNET_STATUS         = -3,          /* Send full status */
117    BNET_TERMINATE      = -4,          /* Conversation terminated, doing close() */
118    BNET_POLL           = -5,          /* Poll request, I'm hanging on a read */
119    BNET_HEARTBEAT      = -6,          /* Heartbeat Response requested */
120    BNET_HB_RESPONSE    = -7,          /* Only response permited to HB */
121    BNET_xxxxxxPROMPT   = -8,          /* No longer used -- Prompt for subcommand */
122    BNET_BTIME          = -9,          /* Send UTC btime */
123    BNET_BREAK          = -10,         /* Stop current command -- ctl-c */
124    BNET_START_SELECT   = -11,         /* Start of a selection list */
125    BNET_END_SELECT     = -12,         /* End of a select list */
126    BNET_INVALID_CMD    = -13,         /* Invalid command sent */
127    BNET_CMD_FAILED     = -14,         /* Command failed */
128    BNET_CMD_OK         = -15,         /* Command succeeded */
129    BNET_CMD_BEGIN      = -16,         /* Start command execution */
130    BNET_MSGS_PENDING   = -17,         /* Messages pending */
131    BNET_MAIN_PROMPT    = -18,         /* Server ready and waiting */
132    BNET_SELECT_INPUT   = -19,         /* Return selection input */
133    BNET_WARNING_MSG    = -20,         /* Warning message */
134    BNET_ERROR_MSG      = -21,         /* Error message -- command failed */
135    BNET_INFO_MSG       = -22,         /* Info message -- status line */
136    BNET_RUN_CMD        = -23,         /* Run command follows */
137    BNET_YESNO          = -24,         /* Request yes no response */
138    BNET_START_RTREE    = -25,         /* Start restore tree mode */
139    BNET_END_RTREE      = -26,         /* End restore tree mode */
140    BNET_SUB_PROMPT     = -27,         /* Indicate we are at a subprompt */
141    BNET_TEXT_INPUT     = -28,         /* Get text input from user */
142    BNET_EXT_TERMINATE  = -29,         /* A Terminate condition has been met and
143                                          already reported somewhere else */
144    BNET_FDCALLED       = -30          /* The FD should keep the connection for a new job */
145 };
146 
147 /*
148  * These bits ares set in the packet length field.  Attempt to
149  *  keep the number of bits to a minimum and instead use the new
150  *  flag field for passing bits using the BNET_HDR_EXTEND bit.
151  *  Note: we must not set the high bit as that indicates a signal.
152  */
153 #define BNET_COMPRESSED (1<<30)       /* set for lz4 compressed data */
154 #define BNET_HDR_EXTEND (1<<29)       /* extended header */
155 
156 /*
157  * The following bits are kept in flags.  The high 16 bits are
158  *  for flags, and the low 16 bits are for other info such as
159  *  compressed data offset (BNET_OFFSET)
160  */
161 #define BNET_IS_CMD           (1<<28)     /* set for command data */
162 #define BNET_OFFSET           (1<<27)     /* Data compression offset specified */
163 #define BNET_NOCOMPRESS       (1<<25)     /* Disable compression */
164 #define BNET_DATACOMPRESSED   (1<<24)     /* Data compression */
165 
166 #define BNET_SETBUF_READ  1           /* Arg for bnet_set_buffer_size */
167 #define BNET_SETBUF_WRITE 2           /* Arg for bnet_set_buffer_size */
168 
169 /*
170  * Return status from bnet_recv()
171  * Note, the HARDEOF and ERROR refer to comm status/problems
172  *  rather than the BNET_xxx above, which are software signals.
173  */
174 enum {
175    BNET_SIGNAL         = -1,
176    BNET_HARDEOF        = -2,
177    BNET_ERROR          = -3,
178    BNET_COMMAND        = -4
179 };
180 
181 /*
182  * Inter-daemon commands
183  * When BNET_IS_CMD is on, the next int32 is a command
184  */
185 #define BNET_CMD_SIZE sizeof(int32_t)
186 
187 enum {
188    BNET_CMD_NONE       =  0, /* reserved */
189    BNET_CMD_ACK_HASH   =  1, /* backup  SD->FD  SD already know this hash, don't need the block */
190    BNET_CMD_UNK_HASH   =  2, /* restore SD->FD  hash is unknown */
191    BNET_CMD_GET_HASH   =  3, /* backup  SD->FD  SD ask FD to send the corresponding block */
192                              /* restore FD->SD  FD ask SD to send the corresponding block */
193    BNET_CMD_STO_BLOCK  =  4, /* backup  FD->SD  FD send requested block */
194    BNET_CMD_REC_ACK    =  5, /* restore FD->SD  FD has consumed records from the buffer */
195    BNET_CMD_STP_THREAD =  6, /* restore FD->SD  SD must stop thread */
196    BNET_CMD_STP_FLOWCTRL = 7 /* backup FD->SD  SD must stop sending flowcontrol information */
197 };
198 
199 /*
200  * TLS enabling values. Value is important for comparison, ie:
201  * if (tls_remote_need < BNET_TLS_REQUIRED) { ... }
202  */
203 enum {
204    BNET_TLS_NONE        = 0,          /* cannot do TLS */
205    BNET_TLS_OK          = 1,          /* can do, but not required on my end */
206    BNET_TLS_REQUIRED    = 2           /* TLS is required */
207 };
208 
209 const char *bnet_cmd_to_name(int val);
210 
211 BSOCK *new_bsock();
212 /*
213  * Completely release the socket packet, and NULL the pointer
214  */
215 #define free_bsock(a) free_bsockcore(a)
216 
217 /*
218  * Does the socket exist and is it open?
219  */
220 #define is_bsock_open(a) is_bsockcore_open(a)
221 
222 #endif /* __BSOCK_H_ */
223