Line data Source code
1 : #include "../burp.h"
2 : #include "../asfd.h"
3 : #include "../async.h"
4 : #include "../cmd.h"
5 : #include "../conf.h"
6 : #include "../conffile.h"
7 : #include "../handy.h"
8 : #include "../incexc_recv.h"
9 : #include "../incexc_send.h"
10 : #include "../iobuf.h"
11 : #include "../log.h"
12 : #include "autoupgrade.h"
13 : #include "extra_comms.h"
14 :
15 : #ifndef HAVE_WIN32
16 : #include <sys/utsname.h>
17 : #endif
18 :
19 : static const char *server_supports(const char *feat, const char *wanted)
20 : {
21 140 : return strstr(feat, wanted);
22 : }
23 :
24 18 : static const char *server_supports_autoupgrade(const char *feat)
25 : {
26 : // 1.3.0 servers did not list the features, but the only feature
27 : // that was supported was autoupgrade.
28 18 : if(!strcmp(feat, "extra_comms_begin ok")) return "ok";
29 18 : return server_supports(feat, ":autoupgrade:");
30 : }
31 :
32 : #include <librsync.h>
33 :
34 21 : int extra_comms_client(struct async *as, struct conf **confs,
35 : enum action *action, struct strlist *failover, char **incexc)
36 : {
37 21 : int ret=-1;
38 21 : char *feat=NULL;
39 21 : char *seed_src=NULL;
40 21 : char *seed_dst=NULL;
41 : struct asfd *asfd;
42 : struct iobuf *rbuf;
43 21 : const char *orig_client=NULL;
44 21 : asfd=as->asfd;
45 21 : rbuf=asfd->rbuf;
46 :
47 21 : if(asfd->write_str(asfd, CMD_GEN, "extra_comms_begin"))
48 : {
49 1 : logp("Problem requesting extra_comms_begin\n");
50 1 : goto end;
51 : }
52 : // Servers greater than 1.3.0 will list the extra_comms
53 : // features they support.
54 20 : if(asfd->read(asfd))
55 : {
56 1 : logp("Problem reading response to extra_comms_begin\n");
57 1 : goto end;
58 : }
59 19 : if(rbuf->cmd!=CMD_GEN
60 19 : || strncmp_w(rbuf->buf, "extra_comms_begin ok"))
61 : {
62 1 : iobuf_log_unexpected(rbuf, __func__);
63 1 : goto end;
64 : }
65 18 : feat=rbuf->buf;
66 18 : rbuf->buf=NULL;
67 18 : logp("%s\n", feat);
68 18 : iobuf_init(rbuf);
69 :
70 : // Can add extra bits here. The first extra bit is the
71 : // autoupgrade stuff.
72 18 : if(server_supports_autoupgrade(feat)
73 1 : && get_string(confs[OPT_AUTOUPGRADE_DIR])
74 1 : && get_string(confs[OPT_AUTOUPGRADE_OS])
75 1 : && autoupgrade_client(as, confs))
76 : goto end;
77 :
78 :
79 : // :srestore: means that the server wants to do a restore.
80 34 : if(server_supports(feat, ":srestore:"))
81 : {
82 6 : logp("Server wants to initiate a restore\n");
83 6 : if(*action==ACTION_MONITOR)
84 : {
85 1 : logp("Client is in monitor mode, so ignoring\n");
86 : }
87 5 : else if(get_int(confs[OPT_SERVER_CAN_RESTORE]))
88 : {
89 4 : logp("Client accepts.\n");
90 4 : if(incexc_recv_client_restore(asfd, incexc, confs))
91 : goto end;
92 4 : if(*incexc)
93 : {
94 4 : if(conf_parse_incexcs_srestore(confs, *incexc))
95 : goto end;
96 2 : *action=ACTION_RESTORE;
97 2 : log_restore_settings(confs, 1);
98 : }
99 : }
100 : else
101 : {
102 1 : logp("Client configuration says no\n");
103 1 : if(asfd->write_str(asfd, CMD_GEN, "srestore not ok"))
104 : goto end;
105 : }
106 : }
107 :
108 : // Needs to be after the srestore stuff, as the server may set
109 : // orig_client in the server-initiated restore file.
110 15 : if((orig_client=get_string(confs[OPT_ORIG_CLIENT])))
111 : {
112 4 : char str[512]="";
113 4 : snprintf(str, sizeof(str), "orig_client=%s", orig_client);
114 8 : if(!server_supports(feat, ":orig_client:"))
115 : {
116 1 : logp("Server does not support switching client.\n");
117 1 : goto end;
118 : }
119 3 : if(asfd->write_str(asfd, CMD_GEN, str)
120 3 : || asfd_read_expect(asfd, CMD_GEN, "orig_client ok"))
121 : {
122 1 : logp("Problem requesting %s\n", str);
123 1 : goto end;
124 : }
125 2 : logp("Switched to client %s\n", orig_client);
126 : }
127 :
128 : // :sincexc: is for the server giving the client the
129 : // incexc config.
130 26 : if(*action==ACTION_BACKUP
131 13 : || *action==ACTION_BACKUP_TIMED
132 3 : || *action==ACTION_TIMER_CHECK)
133 : {
134 20 : if(!*incexc && server_supports(feat, ":sincexc:"))
135 : {
136 2 : logp("Server is setting includes/excludes.\n");
137 2 : if(get_int(confs[OPT_SERVER_CAN_OVERRIDE_INCLUDES]))
138 : {
139 1 : logp("Client accepts.\n");
140 1 : if(incexc_recv_client(asfd, incexc, confs))
141 : goto end;
142 1 : if(*incexc && conf_parse_incexcs_buf(confs,
143 : *incexc)) goto end;
144 : }
145 : else
146 : {
147 1 : logp("Client configuration says no\n");
148 : }
149 : }
150 : }
151 :
152 26 : if(server_supports(feat, ":counters_json:"))
153 : {
154 1 : if(asfd->write_str(asfd, CMD_GEN, "counters_json ok"))
155 : goto end;
156 1 : set_int(confs[OPT_SEND_CLIENT_CNTR], 1);
157 : }
158 :
159 : // :incexc: is for the client sending the server the
160 : // incexc conf so that it better knows what to do on
161 : // resume.
162 26 : if(server_supports(feat, ":incexc:")
163 0 : && incexc_send_client(asfd, confs))
164 : goto end;
165 :
166 26 : if(server_supports(feat, ":uname:"))
167 : {
168 1 : const char *clientos=NULL;
169 : #ifdef HAVE_WIN32
170 : #ifdef _WIN64
171 : clientos="Windows 64bit";
172 : #else
173 : clientos="Windows 32bit";
174 : #endif
175 : #else
176 : struct utsname utsname;
177 1 : if(!uname(&utsname))
178 1 : clientos=(const char *)utsname.sysname;
179 : #endif
180 1 : if(clientos)
181 : {
182 1 : char *msg=NULL;
183 1 : if(astrcat(&msg, "uname=", __func__)
184 1 : || astrcat(&msg, clientos, __func__))
185 : goto end;
186 1 : if(asfd->write_str(asfd, CMD_GEN, msg))
187 : {
188 0 : free_w(&msg);
189 0 : goto end;
190 : }
191 1 : free_w(&msg);
192 : }
193 : }
194 :
195 26 : if(server_supports(feat, ":msg:"))
196 : {
197 1 : set_int(confs[OPT_MESSAGE], 1);
198 1 : if(asfd->write_str(asfd, CMD_GEN, "msg"))
199 : goto end;
200 : }
201 :
202 : #ifdef HAVE_BLAKE2
203 : if(server_supports(feat, ":rshash=blake2:"))
204 : {
205 : set_e_rshash(confs[OPT_RSHASH], RSHASH_BLAKE2);
206 : // Send choice to server.
207 : if(asfd->write_str(asfd, CMD_GEN, "rshash=blake2"))
208 : goto end;
209 : }
210 : else
211 : #endif
212 13 : set_e_rshash(confs[OPT_RSHASH], RSHASH_MD4);
213 :
214 26 : if(server_supports(feat, ":failover:"))
215 : {
216 0 : if(*action==ACTION_BACKUP
217 0 : || *action==ACTION_BACKUP_TIMED)
218 : {
219 0 : char msg[64]="";
220 0 : int left=0;
221 0 : struct strlist *f=NULL;
222 0 : for(f=failover; f; f=f->next)
223 0 : left++;
224 0 : snprintf(msg, sizeof(msg),
225 : "backup_failovers_left=%d", left);
226 0 : if(asfd->write_str(asfd, CMD_GEN, msg))
227 : goto end;
228 : }
229 : }
230 :
231 13 : seed_src=get_string(confs[OPT_SEED_SRC]);
232 13 : seed_dst=get_string(confs[OPT_SEED_DST]);
233 13 : if(seed_src && *seed_src
234 0 : && seed_dst && *seed_dst
235 0 : && server_supports(feat, ":seed:"))
236 : {
237 0 : char *msg=NULL;
238 0 : logp("Seeding from %s\n", seed_src);
239 0 : if(astrcat(&msg, "seed_src=", __func__)
240 0 : || astrcat(&msg, seed_src, __func__)
241 0 : || asfd->write_str(asfd, CMD_GEN, msg))
242 : {
243 0 : free_w(&msg);
244 0 : goto end;
245 : }
246 0 : free_w(&msg);
247 0 : logp("Seeding to %s\n", seed_dst);
248 0 : if(astrcat(&msg, "seed_dst=", __func__)
249 0 : || astrcat(&msg, seed_dst, __func__)
250 0 : || asfd->write_str(asfd, CMD_GEN, msg))
251 : {
252 0 : free_w(&msg);
253 0 : goto end;
254 : }
255 0 : free_w(&msg);
256 : }
257 :
258 26 : if(server_supports(feat, ":vss_restore:"))
259 : {
260 0 : enum vss_restore vss_restore=(enum vss_restore)
261 0 : get_int(confs[OPT_VSS_RESTORE]);
262 0 : if(vss_restore==VSS_RESTORE_OFF
263 0 : && asfd->write_str(asfd, CMD_GEN, "vss_restore=off"))
264 : goto end;
265 0 : if(vss_restore==VSS_RESTORE_OFF_STRIP
266 0 : && asfd->write_str(asfd, CMD_GEN, "vss_restore=strip"))
267 : goto end;
268 : }
269 :
270 26 : if(server_supports(feat, ":regex_icase:"))
271 : {
272 0 : if(get_int(confs[OPT_REGEX_CASE_INSENSITIVE]))
273 : {
274 0 : if(asfd->write_str(asfd, CMD_GEN,
275 : "regex_icase=1"))
276 : goto end;
277 : }
278 : }
279 :
280 13 : if(asfd->write_str(asfd, CMD_GEN, "extra_comms_end")
281 13 : || asfd_read_expect(asfd, CMD_GEN, "extra_comms_end ok"))
282 : {
283 1 : logp("Problem requesting extra_comms_end\n");
284 1 : goto end;
285 : }
286 :
287 : ret=0;
288 : end:
289 21 : free_w(&feat);
290 21 : return ret;
291 : }
|