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