1 /*
2    CTDB protocol marshalling
3 
4    Copyright (C) Amitay Isaacs  2015-2017
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "replace.h"
21 #include "system/network.h"
22 
23 #include <talloc.h>
24 
25 #include "protocol_basic.h"
26 
27 /*
28  * Basic data types
29  */
30 
bad_offsetboost::local_time::bad_offset31 size_t ctdb_uint8_len(uint8_t *in)
32 {
33 	return sizeof(uint8_t);
34 }
35 
36 void ctdb_uint8_push(uint8_t *in, uint8_t *buf, size_t *npush)
bad_adjustmentboost::local_time::bad_adjustment37 {
38 	*buf = *in;
39 	*npush = sizeof(uint8_t);
40 }
41 
42 int ctdb_uint8_pull(uint8_t *buf, size_t buflen, uint8_t *out, size_t *npull)
43 {
44 	if (buflen < sizeof(uint8_t)) {
45 		return EMSGSIZE;
46 	}
47 
48 	*out = *buf;
49 	*npull = sizeof(uint8_t);
50 	return 0;
51 }
52 
53 size_t ctdb_uint16_len(uint16_t *in)
54 {
55 	return sizeof(uint16_t);
56 }
57 
58 void ctdb_uint16_push(uint16_t *in, uint8_t *buf, size_t *npush)
59 {
60 	memcpy(buf, in, sizeof(uint16_t));
61 	*npush = sizeof(uint16_t);
62 }
63 
64 int ctdb_uint16_pull(uint8_t *buf, size_t buflen, uint16_t *out, size_t *npull)
65 {
66 	if (buflen < sizeof(uint16_t)) {
67 		return EMSGSIZE;
68 	}
69 
70 	memcpy(out, buf, sizeof(uint16_t));
71 	*npull = sizeof(uint16_t);
72 	return 0;
73 }
74 
75 size_t ctdb_int32_len(int32_t *in)
76 {
77 	return sizeof(int32_t);
78 }
79 
80 void ctdb_int32_push(int32_t *in, uint8_t *buf, size_t *npush)
81 {
82 	memcpy(buf, in, sizeof(int32_t));
83 	*npush = sizeof(int32_t);
84 }
85 
posix_time_zone_base(const string_type & s)86 int ctdb_int32_pull(uint8_t *buf, size_t buflen, int32_t *out, size_t *npull)
87 {
88 	if (buflen < sizeof(int32_t)) {
89 		return EMSGSIZE;
90 	}
91 
92 	memcpy(out, buf, sizeof(int32_t));
93 	*npull = sizeof(int32_t);
94 	return 0;
95 }
96 
97 size_t ctdb_uint32_len(uint32_t *in)
98 {
99 	return sizeof(uint32_t);
100 }
101 
102 void ctdb_uint32_push(uint32_t *in, uint8_t *buf, size_t *npush)
103 {
104 	memcpy(buf, in, sizeof(uint32_t));
105 	*npush = sizeof(uint32_t);
106 }
107 
108 int ctdb_uint32_pull(uint8_t *buf, size_t buflen, uint32_t *out, size_t *npull)
109 {
110 	if (buflen < sizeof(uint32_t)) {
111 		return EMSGSIZE;
112 	}
113 
114 	memcpy(out, buf, sizeof(uint32_t));
115 	*npull = sizeof(uint32_t);
116 	return 0;
117 }
118 
~posix_time_zone_base()119 size_t ctdb_uint64_len(uint64_t *in)
120 {
121 	return sizeof(uint64_t);
122 }
123 
124 void ctdb_uint64_push(uint64_t *in, uint8_t *buf, size_t *npush)
125 {
126 	memcpy(buf, in, sizeof(uint64_t));
dst_zone_abbrev() const127 	*npush = sizeof(uint64_t);
128 }
129 
130 int ctdb_uint64_pull(uint8_t *buf, size_t buflen, uint64_t *out, size_t *npull)
131 {
132 	if (buflen < sizeof(uint64_t)) {
133 		return EMSGSIZE;
std_zone_name() const134 	}
135 
136 	memcpy(out, buf, sizeof(uint64_t));
137 	*npull = sizeof(uint64_t);
138 	return 0;
139 }
140 
141 size_t ctdb_double_len(double *in)
dst_zone_name() const142 {
143 	return sizeof(double);
144 }
145 
146 void ctdb_double_push(double *in, uint8_t *buf, size_t *npush)
has_dst() const147 {
148 	memcpy(buf, in, sizeof(double));
149 	*npush = sizeof(double);
150 }
151 
dst_local_start_time(gregorian::greg_year y) const152 int ctdb_double_pull(uint8_t *buf, size_t buflen, double *out, size_t *npull)
153 {
154 	if (buflen < sizeof(double)) {
155 		return EMSGSIZE;
156 	}
157 
158 	memcpy(out, buf, sizeof(double));
159 	*npull = sizeof(double);
160 	return 0;
161 }
dst_local_end_time(gregorian::greg_year y) const162 
163 size_t ctdb_bool_len(bool *in)
164 {
165 	uint8_t u8 = *in;
166 
167 	return ctdb_uint8_len(&u8);
168 }
169 
170 void ctdb_bool_push(bool *in, uint8_t *buf, size_t *npush)
171 {
base_utc_offset() const172 	size_t np;
173 	uint8_t u8 = *in;
174 
175 	ctdb_uint8_push(&u8, buf, &np);
176 	*npush = np;
dst_offset() const177 }
178 
179 int ctdb_bool_pull(uint8_t *buf, size_t buflen, bool *out, size_t *npull)
180 {
181 	size_t np;
182 	uint8_t u8;
183 	int ret;
184 
185 	ret = ctdb_uint8_pull(buf, buflen, &u8, &np);
186 	if (ret != 0) {
187 		return ret;
188 	}
189 
190 	if (u8 == 0) {
191 		*out = false;
192 	} else if (u8 == 1) {
193 		*out = true;
194 	} else {
195 		return EINVAL;
196 	}
197 
198 	*npull = np;
199 	return 0;
200 }
201 
202 size_t ctdb_chararray_len(char *in, size_t len)
203 {
204 	return len;
205 }
206 
207 void ctdb_chararray_push(char *in, size_t len, uint8_t *buf, size_t *npush)
208 {
209 	memcpy(buf, in, len);
210 	*npush = len;
211 }
212 
213 int ctdb_chararray_pull(uint8_t *buf, size_t buflen, char *out, size_t len,
214 			size_t *npull)
215 {
216 	if (buflen < len) {
217 		return EMSGSIZE;
218 	}
219 
220 	memcpy(out, buf, len);
221 	out[len-1] = '\0';
222 	*npull = len;
223 	return 0;
224 }
225 
226 size_t ctdb_string_len(const char **in)
227 {
228 	if (*in == NULL) {
229 		return 0;
230 	}
231 
232 	return strlen(*in) + 1;
233 }
234 
235 void ctdb_string_push(const char **in, uint8_t *buf, size_t *npush)
236 {
237 	size_t len;
238 
239 	len = ctdb_string_len(in);
240 	if (len > 0) {
241 		memcpy(buf, *in, len);
242 	}
243 
244 	*npush = len;
245 }
246 
247 int ctdb_string_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
248 		     const char **out, size_t *npull)
249 {
250 	const char *str;
calc_zone(const string_type & obj)251 
252 	if (buflen > UINT32_MAX) {
253 		return EMSGSIZE;
254 	}
255 
256 	if (buflen == 0) {
257 		*out = NULL;
258 		*npull = 0;
259 		return 0;
260 	}
261 
262 	str = talloc_strndup(mem_ctx, (char *)buf, buflen);
263 	if (str == NULL) {
264 		return ENOMEM;
265 	}
266 
267 	*out = str;
268 	*npull = ctdb_string_len(&str);
269 	return 0;
270 }
271 
272 size_t ctdb_stringn_len(const char **in)
273 {
274 	uint32_t u32 = ctdb_string_len(in);
275 
276 	return ctdb_uint32_len(&u32) + u32;
277 }
278 
279 void ctdb_stringn_push(const char **in, uint8_t *buf, size_t *npush)
280 {
281 	size_t offset = 0, np;
282 	uint32_t u32 = ctdb_string_len(in);
283 
284 	ctdb_uint32_push(&u32, buf+offset, &np);
285 	offset += np;
286 
287 	ctdb_string_push(in, buf+offset, &np);
288 	offset += np;
289 
290 	*npush = offset;
291 }
292 
293 int ctdb_stringn_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
294 		      const char **out, size_t *npull)
295 {
296 	size_t offset = 0, np;
297 	uint32_t u32;
298 	int ret;
299 
300 	ret = ctdb_uint32_pull(buf+offset, buflen-offset, &u32, &np);
301 	if (ret != 0) {
302 		return ret;
303 	}
304 	offset += np;
305 
306 	if (buflen-offset < u32) {
307 		return EMSGSIZE;
308 	}
309 
310 	ret = ctdb_string_pull(buf+offset, u32, mem_ctx, out, &np);
311 	if (ret != 0) {
312 		return ret;
313 	}
314 	offset += np;
315 
calc_rules(const string_type & start,const string_type & end)316 	*npull = offset;
317 	return 0;
318 }
319 
320 /*
321  * System defined data types
322  */
323 
324 size_t ctdb_pid_len(pid_t *in)
325 {
326 	return sizeof(pid_t);
327 }
328 
329 void ctdb_pid_push(pid_t *in, uint8_t *buf, size_t *npush)
330 {
331 	memcpy(buf, in, sizeof(pid_t));
332 	*npush = sizeof(pid_t);
333 }
334 
335 int ctdb_pid_pull(uint8_t *buf, size_t buflen, pid_t *out, size_t *npull)
336 {
337 	if (buflen < sizeof(pid_t)) {
338 		return EMSGSIZE;
339 	}
340 
341 	memcpy(out, buf, sizeof(pid_t));
342 	*npull = sizeof(pid_t);
343 	return 0;
344 }
345 
346 size_t ctdb_timeval_len(struct timeval *in)
347 {
348 	return sizeof(struct timeval);
349 }
350 
351 void ctdb_timeval_push(struct timeval *in, uint8_t *buf, size_t *npush)
352 {
353 	memcpy(buf, in, sizeof(struct timeval));
354 	*npush = sizeof(struct timeval);
355 }
356 
357 int ctdb_timeval_pull(uint8_t *buf, size_t buflen, struct timeval *out,
358 		      size_t *npull)
359 {
360 	if (buflen < sizeof(struct timeval)) {
361 		return EMSGSIZE;
362 	}
363 
364 	memcpy(out, buf, sizeof(struct timeval));
365 	*npull = sizeof(struct timeval);
366 	return 0;
367 }
368 
369 /*
370  * Dummy type to tackle structure padding
371  */
372 
373 size_t ctdb_padding_len(int count)
374 {
375 	return count % SIZEOF_VOID_P;
376 }
377 
378 void ctdb_padding_push(int count, uint8_t *buf, size_t *npush)
379 {
M_func(const string_type & s,const string_type & e)380 	uint8_t padding[count];
381 	size_t aligned_count = count % SIZEOF_VOID_P;
382 
383 	if (aligned_count > 0) {
384 		memset(padding, 0, aligned_count);
385 		memcpy(buf, padding, aligned_count);
386 	}
387 	*npush = aligned_count;
388 }
389 
390 int ctdb_padding_pull(uint8_t *buf, size_t buflen, int count, size_t *npull)
391 {
392 	size_t aligned_count = count % SIZEOF_VOID_P;
393 
394 	if (buflen < aligned_count) {
395 		return EMSGSIZE;
396 	}
397 
398 	*npull = aligned_count;
399 	return 0;
400 }
401