ctdb-protocol: Fix marshalling for a string with length
[vlendec/samba-autobuild/.git] / ctdb / protocol / protocol_basic.c
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 #include <tdb.h>
25
26 #include "protocol.h"
27 #include "protocol_private.h"
28
29 /*
30  * Basic data types
31  */
32
33 size_t ctdb_uint8_len(uint8_t *in)
34 {
35         return sizeof(uint8_t);
36 }
37
38 void ctdb_uint8_push(uint8_t *in, uint8_t *buf, size_t *npush)
39 {
40         *buf = *in;
41         *npush = sizeof(uint8_t);
42 }
43
44 int ctdb_uint8_pull(uint8_t *buf, size_t buflen, uint8_t *out, size_t *npull)
45 {
46         if (buflen < sizeof(uint8_t)) {
47                 return EMSGSIZE;
48         }
49
50         *out = *buf;
51         *npull = sizeof(uint8_t);
52         return 0;
53 }
54
55 size_t ctdb_uint16_len(uint16_t *in)
56 {
57         return sizeof(uint16_t);
58 }
59
60 void ctdb_uint16_push(uint16_t *in, uint8_t *buf, size_t *npush)
61 {
62         memcpy(buf, in, sizeof(uint16_t));
63         *npush = sizeof(uint16_t);
64 }
65
66 int ctdb_uint16_pull(uint8_t *buf, size_t buflen, uint16_t *out, size_t *npull)
67 {
68         if (buflen < sizeof(uint16_t)) {
69                 return EMSGSIZE;
70         }
71
72         memcpy(out, buf, sizeof(uint16_t));
73         *npull = sizeof(uint16_t);
74         return 0;
75 }
76
77 size_t ctdb_int32_len(int32_t *in)
78 {
79         return sizeof(int32_t);
80 }
81
82 void ctdb_int32_push(int32_t *in, uint8_t *buf, size_t *npush)
83 {
84         memcpy(buf, in, sizeof(int32_t));
85         *npush = sizeof(int32_t);
86 }
87
88 int ctdb_int32_pull(uint8_t *buf, size_t buflen, int32_t *out, size_t *npull)
89 {
90         if (buflen < sizeof(int32_t)) {
91                 return EMSGSIZE;
92         }
93
94         memcpy(out, buf, sizeof(int32_t));
95         *npull = sizeof(int32_t);
96         return 0;
97 }
98
99 size_t ctdb_uint32_len(uint32_t *in)
100 {
101         return sizeof(uint32_t);
102 }
103
104 void ctdb_uint32_push(uint32_t *in, uint8_t *buf, size_t *npush)
105 {
106         memcpy(buf, in, sizeof(uint32_t));
107         *npush = sizeof(uint32_t);
108 }
109
110 int ctdb_uint32_pull(uint8_t *buf, size_t buflen, uint32_t *out, size_t *npull)
111 {
112         if (buflen < sizeof(uint32_t)) {
113                 return EMSGSIZE;
114         }
115
116         memcpy(out, buf, sizeof(uint32_t));
117         *npull = sizeof(uint32_t);
118         return 0;
119 }
120
121 size_t ctdb_uint64_len(uint64_t *in)
122 {
123         return sizeof(uint64_t);
124 }
125
126 void ctdb_uint64_push(uint64_t *in, uint8_t *buf, size_t *npush)
127 {
128         memcpy(buf, in, sizeof(uint64_t));
129         *npush = sizeof(uint64_t);
130 }
131
132 int ctdb_uint64_pull(uint8_t *buf, size_t buflen, uint64_t *out, size_t *npull)
133 {
134         if (buflen < sizeof(uint64_t)) {
135                 return EMSGSIZE;
136         }
137
138         memcpy(out, buf, sizeof(uint64_t));
139         *npull = sizeof(uint64_t);
140         return 0;
141 }
142
143 size_t ctdb_double_len(double *in)
144 {
145         return sizeof(double);
146 }
147
148 void ctdb_double_push(double *in, uint8_t *buf, size_t *npush)
149 {
150         memcpy(buf, in, sizeof(double));
151         *npush = sizeof(double);
152 }
153
154 int ctdb_double_pull(uint8_t *buf, size_t buflen, double *out, size_t *npull)
155 {
156         if (buflen < sizeof(double)) {
157                 return EMSGSIZE;
158         }
159
160         memcpy(out, buf, sizeof(double));
161         *npull = sizeof(double);
162         return 0;
163 }
164
165 size_t ctdb_bool_len(bool *in)
166 {
167         uint8_t u8 = *in;
168
169         return ctdb_uint8_len(&u8);
170 }
171
172 void ctdb_bool_push(bool *in, uint8_t *buf, size_t *npush)
173 {
174         size_t np;
175         uint8_t u8 = *in;
176
177         ctdb_uint8_push(&u8, buf, &np);
178         *npush = np;
179 }
180
181 int ctdb_bool_pull(uint8_t *buf, size_t buflen, bool *out, size_t *npull)
182 {
183         size_t np;
184         uint8_t u8;
185         int ret;
186
187         ret = ctdb_uint8_pull(buf, buflen, &u8, &np);
188         if (ret != 0) {
189                 return ret;
190         }
191
192         if (u8 == 0) {
193                 *out = false;
194         } else if (u8 == 1) {
195                 *out = true;
196         } else {
197                 return EINVAL;
198         }
199
200         *npull = np;
201         return 0;
202 }
203
204 size_t ctdb_chararray_len(char *in, size_t len)
205 {
206         return len;
207 }
208
209 void ctdb_chararray_push(char *in, size_t len, uint8_t *buf, size_t *npush)
210 {
211         memcpy(buf, in, len);
212         *npush = len;
213 }
214
215 int ctdb_chararray_pull(uint8_t *buf, size_t buflen, char *out, size_t len,
216                         size_t *npull)
217 {
218         if (buflen < len) {
219                 return EMSGSIZE;
220         }
221
222         memcpy(out, buf, len);
223         out[len-1] = '\0';
224         *npull = len;
225         return 0;
226 }
227
228 size_t ctdb_string_len(const char **in)
229 {
230         if (*in == NULL) {
231                 return 0;
232         }
233
234         return strlen(*in) + 1;
235 }
236
237 void ctdb_string_push(const char **in, uint8_t *buf, size_t *npush)
238 {
239         size_t len;
240
241         len = ctdb_string_len(in);
242         if (len > 0) {
243                 memcpy(buf, *in, len);
244         }
245
246         *npush = len;
247 }
248
249 int ctdb_string_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
250                      const char **out, size_t *npull)
251 {
252         const char *str;
253
254         if (buflen > UINT32_MAX) {
255                 return EMSGSIZE;
256         }
257
258         if (buflen == 0) {
259                 *out = NULL;
260                 *npull = 0;
261                 return 0;
262         }
263
264         str = talloc_strndup(mem_ctx, (char *)buf, buflen);
265         if (str == NULL) {
266                 return ENOMEM;
267         }
268
269         *out = str;
270         *npull = ctdb_string_len(&str);
271         return 0;
272 }
273
274 size_t ctdb_stringn_len(const char **in)
275 {
276         uint32_t u32 = ctdb_string_len(in);
277
278         return ctdb_uint32_len(&u32) + u32;
279 }
280
281 void ctdb_stringn_push(const char **in, uint8_t *buf, size_t *npush)
282 {
283         size_t offset = 0, np;
284         uint32_t u32 = ctdb_string_len(in);
285
286         ctdb_uint32_push(&u32, buf+offset, &np);
287         offset += np;
288
289         ctdb_string_push(in, buf+offset, &np);
290         offset += np;
291
292         *npush = offset;
293 }
294
295 int ctdb_stringn_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
296                       const char **out, size_t *npull)
297 {
298         size_t offset = 0, np;
299         uint32_t u32;
300         int ret;
301
302         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &u32, &np);
303         if (ret != 0) {
304                 return ret;
305         }
306         offset += np;
307
308         if (buflen-offset < u32) {
309                 return EMSGSIZE;
310         }
311
312         ret = ctdb_string_pull(buf+offset, u32, mem_ctx, out, &np);
313         if (ret != 0) {
314                 return ret;
315         }
316         offset += np;
317
318         *npull = offset;
319         return 0;
320 }
321
322 /*
323  * System defined data types
324  */
325
326 size_t ctdb_pid_len(pid_t pid)
327 {
328         return sizeof(pid_t);
329 }
330
331 void ctdb_pid_push(pid_t pid, uint8_t *buf)
332 {
333         memcpy(buf, &pid, sizeof(pid_t));
334 }
335
336 int ctdb_pid_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
337                   pid_t *out)
338 {
339         if (buflen < sizeof(pid_t)) {
340                 return EMSGSIZE;
341         }
342
343         *out = *(pid_t *)buf;
344         return 0;
345 }