]> git.ozlabs.org Git - petitboot/blob - lib/pb-protocol/pb-protocol.c
discover/grub2: Allow to separate the --id argument using a space char
[petitboot] / lib / pb-protocol / pb-protocol.c
1
2 #include <assert.h>
3 #include <errno.h>
4 #include <string.h>
5 #include <stdbool.h>
6 #include <stdint.h>
7 #include <asm/byteorder.h>
8
9 #include <talloc/talloc.h>
10 #include <list/list.h>
11 #include <log/log.h>
12
13 #include "pb-protocol.h"
14
15
16 /* Message format:
17  *
18  * 4-byte action, determines the remaining message content
19  * 4-byte total payload len
20  *   - not including action and payload len header
21  *
22  * action = 0x1: device add message
23  *  payload:
24  *   4-byte len, id
25  *   1-byte type
26  *   4-byte len, name
27  *   4-byte len, description
28  *   4-byte len, icon_file
29  *
30  *   4-byte option count
31  *   for each option:
32  *    4-byte len, id
33  *    4-byte len, name
34  *    4-byte len, description
35  *    4-byte len, icon_file
36  *    4-byte len, boot_image_file
37  *    4-byte len, initrd_file
38  *    4-byte len, dtb_file
39  *    4-byte len, boot_args
40  *    4-byte len, args_sig_file
41  *
42  * action = 0x2: device remove message
43  *  payload:
44  *   4-byte len, id
45  *
46  * action = 0x3: boot
47  *  payload:
48  *   4-byte len, boot option id
49  *   4-byte len, boot_image_file
50  *   4-byte len, initrd_file
51  *   4-byte len, dtb_file
52  *   4-byte len, boot_args
53  *   4-byte len, args_sig_file
54  *
55  */
56
57 void pb_protocol_dump_device(const struct device *dev, const char *text,
58         FILE *stream)
59 {
60         struct boot_option *opt;
61
62         fprintf(stream, "%snew dev:\n", text);
63         fprintf(stream, "%s\tid:   %s\n", text, dev->id);
64         fprintf(stream, "%s\tname: %s\n", text, dev->name);
65         fprintf(stream, "%s\tdesc: %s\n", text, dev->description);
66         fprintf(stream, "%s\ticon: %s\n", text, dev->icon_file);
67         fprintf(stream, "%s\tboot options:\n", text);
68         list_for_each_entry(&dev->boot_options, opt, list) {
69                 fprintf(stream, "%s\t\tid:   %s\n", text, opt->id);
70                 fprintf(stream, "%s\t\tname: %s\n", text, opt->name);
71                 fprintf(stream, "%s\t\tdesc: %s\n", text, opt->description);
72                 fprintf(stream, "%s\t\ticon: %s\n", text, opt->icon_file);
73                 fprintf(stream, "%s\t\tboot: %s\n", text, opt->boot_image_file);
74                 fprintf(stream, "%s\t\tinit: %s\n", text, opt->initrd_file);
75                 fprintf(stream, "%s\t\tdtb:  %s\n", text, opt->dtb_file);
76                 fprintf(stream, "%s\t\targs: %s\n", text, opt->boot_args);
77                 fprintf(stream, "%s\t\tasig: %s\n", text, opt->args_sig_file);
78                 fprintf(stream, "%s\t\ttype: %s\n", text,
79                         opt->type == DISCOVER_BOOT_OPTION ? "boot" : "plugin");
80         }
81 }
82
83 int pb_protocol_device_cmp(const struct device *a, const struct device *b)
84 {
85         return !strcmp(a->id, b->id);
86 }
87
88 int pb_protocol_boot_option_cmp(const struct boot_option *a,
89         const struct boot_option *b)
90 {
91         return !strcmp(a->id, b->id);
92 }
93
94 /* Write a string into the buffer, starting at pos.
95  *
96  * Returns the total length used for the write, including length header.
97  */
98 int pb_protocol_serialise_string(char *pos, const char *str)
99 {
100         int len = 0;
101
102         if (!pos)
103                 return 0;
104
105         if (str)
106                 len = strlen(str);
107
108         *(uint32_t *)pos = __cpu_to_be32(len);
109         pos += sizeof(uint32_t);
110
111         if (str)
112                 memcpy(pos, str, len);
113
114         return len + sizeof(uint32_t);
115 }
116
117 /* Read a string from a buffer, allocating the new string as necessary.
118  *
119  * @param[in] ctx       The talloc context to base the allocation on
120  * @param[in,out] pos   Where to start reading
121  * @param[in,out] len   The amount of data remaining in the buffer
122  * @param[out] str      Pointer to resuling string
123  * @return              zero on success, non-zero on failure
124  */
125 static int read_string(void *ctx, const char **pos, unsigned int *len,
126         char **str)
127 {
128         uint32_t str_len, read_len;
129
130         if (*len < sizeof(uint32_t))
131                 return -1;
132
133         str_len = __be32_to_cpu(*(uint32_t *)(*pos));
134         read_len = sizeof(uint32_t);
135
136         if (read_len + str_len > *len)
137                 return -1;
138
139         if (str_len == 0)
140                 *str = NULL;
141         else
142                 *str = talloc_strndup(ctx, *pos + read_len, str_len);
143
144         read_len += str_len;
145
146         /* all ok, update the caller's pointers */
147         *pos += read_len;
148         *len -= read_len;
149
150         return 0;
151 }
152
153 static int read_u32(const char **pos, unsigned int *len, unsigned int *p)
154 {
155         if (*len < sizeof(uint32_t))
156                 return -1;
157
158         *p = (unsigned int)__be32_to_cpu(*(uint32_t *)(*pos));
159         *pos += sizeof(uint32_t);
160         *len -= sizeof(uint32_t);
161
162         return 0;
163 }
164
165 char *pb_protocol_deserialise_string(void *ctx,
166                 const struct pb_protocol_message *message)
167 {
168         const char *buf;
169         char *str;
170         unsigned int len;
171
172         len = message->payload_len;
173         buf = message->payload;
174
175         if (read_string(ctx, &buf, &len, &str))
176                 return NULL;
177
178         return str;
179 }
180
181 static int optional_strlen(const char *str)
182 {
183         if (!str)
184                 return 0;
185         return strlen(str);
186 }
187
188 int pb_protocol_device_len(const struct device *dev)
189 {
190         return  4 + optional_strlen(dev->id) +
191                 sizeof(dev->type) +
192                 4 + optional_strlen(dev->name) +
193                 4 + optional_strlen(dev->description) +
194                 4 + optional_strlen(dev->icon_file);
195 }
196
197 int pb_protocol_boot_option_len(const struct boot_option *opt)
198 {
199
200         return  4 + optional_strlen(opt->device_id) +
201                 4 + optional_strlen(opt->id) +
202                 4 + optional_strlen(opt->name) +
203                 4 + optional_strlen(opt->description) +
204                 4 + optional_strlen(opt->icon_file) +
205                 4 + optional_strlen(opt->boot_image_file) +
206                 4 + optional_strlen(opt->initrd_file) +
207                 4 + optional_strlen(opt->dtb_file) +
208                 4 + optional_strlen(opt->boot_args) +
209                 4 + optional_strlen(opt->args_sig_file) +
210                 sizeof(opt->is_default) +
211                 sizeof(opt->is_autoboot_default) +
212                 sizeof(opt->type);
213 }
214
215 int pb_protocol_boot_len(const struct boot_command *boot)
216 {
217         return  4 + optional_strlen(boot->option_id) +
218                 4 + optional_strlen(boot->boot_image_file) +
219                 4 + optional_strlen(boot->initrd_file) +
220                 4 + optional_strlen(boot->dtb_file) +
221                 4 + optional_strlen(boot->boot_args) +
222                 4 + optional_strlen(boot->args_sig_file) +
223                 4 + optional_strlen(boot->console);
224 }
225
226 int pb_protocol_boot_status_len(const struct status *status)
227 {
228         return  4 +     /* type */
229                 4 + optional_strlen(status->message) +
230                 4 +     /* backlog */
231                 4;      /* boot_active */
232 }
233
234 int pb_protocol_system_info_len(const struct system_info *sysinfo)
235 {
236         unsigned int len, i;
237
238         len =   4 + optional_strlen(sysinfo->type) +
239                 4 + optional_strlen(sysinfo->identifier) +
240                 4 + 4;
241
242         len +=  4;
243         for (i = 0; i < sysinfo->n_primary; i++)
244                 len += 4 + optional_strlen(sysinfo->platform_primary[i]);
245         len +=  4;
246         for (i = 0; i < sysinfo->n_other; i++)
247                 len += 4 + optional_strlen(sysinfo->platform_other[i]);
248
249         len +=  4;
250         for (i = 0; i < sysinfo->n_bmc_current; i++)
251                 len += 4 + optional_strlen(sysinfo->bmc_current[i]);
252         len +=  4;
253         for (i = 0; i < sysinfo->n_bmc_golden; i++)
254                 len += 4 + optional_strlen(sysinfo->bmc_golden[i]);
255
256         for (i = 0; i < sysinfo->n_interfaces; i++) {
257                 struct interface_info *if_info = sysinfo->interfaces[i];
258                 len +=  4 + if_info->hwaddr_size +
259                         4 + optional_strlen(if_info->name) +
260                         sizeof(if_info->link) +
261                         4 + optional_strlen(if_info->address) +
262                         4 + optional_strlen(if_info->address_v6);
263         }
264
265         for (i = 0; i < sysinfo->n_blockdevs; i++) {
266                 struct blockdev_info *bd_info = sysinfo->blockdevs[i];
267                 len +=  4 + optional_strlen(bd_info->name) +
268                         4 + optional_strlen(bd_info->uuid) +
269                         4 + optional_strlen(bd_info->mountpoint);
270         }
271
272         /* BMC MAC */
273         len += HWADDR_SIZE;
274
275         return len;
276 }
277
278 static int pb_protocol_interface_config_len(struct interface_config *conf)
279 {
280         unsigned int len;
281
282         len =   sizeof(conf->hwaddr) +
283                 4 /* conf->ignore */;
284
285         if (conf->ignore)
286                 return len;
287
288         len += 4 /* conf->method */;
289
290         if (conf->method == CONFIG_METHOD_STATIC) {
291                 len += 4 + optional_strlen(conf->static_config.address);
292                 len += 4 + optional_strlen(conf->static_config.gateway);
293                 len += 4 + optional_strlen(conf->static_config.url);
294         }
295
296         len += 4 /* conf->override */;
297
298         return len;
299 }
300
301 int pb_protocol_config_len(const struct config *config)
302 {
303         unsigned int i, len;
304
305         len =   4 /* config->autoboot_enabled */ +
306                 4 /* config->autoboot_timeout_sec */ +
307                 4 /* config->safe_mode */;
308
309         len += 4;
310         for (i = 0; i < config->network.n_interfaces; i++)
311                 len += pb_protocol_interface_config_len(
312                                 config->network.interfaces[i]);
313
314         len += 4;
315         for (i = 0; i < config->network.n_dns_servers; i++)
316                 len += 4 + optional_strlen(config->network.dns_servers[i]);
317
318         len += 4 + optional_strlen(config->http_proxy);
319         len += 4 + optional_strlen(config->https_proxy);
320
321         len += 4;
322         for (i = 0; i < config->n_autoboot_opts; i++) {
323                 if (config->autoboot_opts[i].boot_type == BOOT_DEVICE_TYPE)
324                         len += 4 + 4;
325                 else
326                         len += 4 + 4 +
327                                 optional_strlen(config->autoboot_opts[i].uuid);
328         }
329
330         len += 4 + 4; /* ipmi_bootdev, ipmi_bootdev_persistent */
331         len += 4; /* ipmi_bootdev_mailbox */
332
333         len += 4; /* allow_writes */
334
335         len += 4; /* n_consoles */
336         for (i = 0; i < config->n_consoles; i++)
337                 len += 4 + optional_strlen(config->consoles[i]);
338
339         len += 4 + optional_strlen(config->boot_console);
340         len += 4; /* manual_console */
341
342         len += 4 + optional_strlen(config->lang);
343
344         return len;
345 }
346
347 int pb_protocol_url_len(const char *url)
348 {
349         /* url + length field */
350         return 4 + optional_strlen(url);
351 }
352
353
354 int pb_protocol_plugin_option_len(const struct plugin_option *opt)
355 {
356         unsigned int i, len = 0;
357
358         len += 4 + optional_strlen(opt->id);
359         len += 4 + optional_strlen(opt->name);
360         len += 4 + optional_strlen(opt->vendor);
361         len += 4 + optional_strlen(opt->vendor_id);
362         len += 4 + optional_strlen(opt->version);
363         len += 4 + optional_strlen(opt->date);
364         len += 4 + optional_strlen(opt->plugin_file);
365
366         len += 4; /* n_executables */
367         for (i = 0; i < opt->n_executables; i++)
368                 len += 4 + optional_strlen(opt->executables[i]);
369
370         return len;
371 }
372
373 int pb_protocol_temp_autoboot_len(const struct autoboot_option *opt)
374 {
375         unsigned int len = 0;
376
377         /* boot_type */
378         len += 4;
379
380         if (opt->boot_type == BOOT_DEVICE_TYPE)
381                 len += 4;
382         else
383                 len += optional_strlen(opt->uuid);
384
385         return len;
386 }
387
388 int pb_protocol_authenticate_len(struct auth_message *msg)
389 {
390         switch (msg->op) {
391         case AUTH_MSG_REQUEST:
392                 /* enum + password + length */
393                 return 4 + 4 + optional_strlen(msg->password);
394         case AUTH_MSG_RESPONSE:
395                 /* enum + bool */
396                 return 4 + 4;
397         case AUTH_MSG_SET:
398                 /* enum + password + password */
399                 return 4 + 4 + optional_strlen(msg->set_password.password) +
400                         4 + optional_strlen(msg->set_password.new_password);
401         case AUTH_MSG_DECRYPT:
402                 /* enum + password + device id */
403                 return 4 + 4 + optional_strlen(msg->decrypt_dev.password) +
404                         4 + optional_strlen(msg->decrypt_dev.device_id);
405         default:
406                 pb_log("%s: invalid input\n", __func__);
407                 return 0;
408         }
409 }
410
411 int pb_protocol_serialise_device(const struct device *dev,
412                 char *buf, int buf_len)
413 {
414         char *pos = buf;
415
416         pos += pb_protocol_serialise_string(pos, dev->id);
417         *(enum device_type *)pos = dev->type;
418         pos += sizeof(enum device_type);
419         pos += pb_protocol_serialise_string(pos, dev->name);
420         pos += pb_protocol_serialise_string(pos, dev->description);
421         pos += pb_protocol_serialise_string(pos, dev->icon_file);
422
423         assert(pos <= buf + buf_len);
424
425         return (pos <= buf + buf_len) ? 0 : -1;
426 }
427
428 int pb_protocol_serialise_boot_option(const struct boot_option *opt,
429                 char *buf, int buf_len)
430 {
431         char *pos = buf;
432
433         pos += pb_protocol_serialise_string(pos, opt->device_id);
434         pos += pb_protocol_serialise_string(pos, opt->id);
435         pos += pb_protocol_serialise_string(pos, opt->name);
436         pos += pb_protocol_serialise_string(pos, opt->description);
437         pos += pb_protocol_serialise_string(pos, opt->icon_file);
438         pos += pb_protocol_serialise_string(pos, opt->boot_image_file);
439         pos += pb_protocol_serialise_string(pos, opt->initrd_file);
440         pos += pb_protocol_serialise_string(pos, opt->dtb_file);
441         pos += pb_protocol_serialise_string(pos, opt->boot_args);
442         pos += pb_protocol_serialise_string(pos, opt->args_sig_file);
443
444         *(bool *)pos = opt->is_default;
445         pos += sizeof(bool);
446         *(bool *)pos = opt->is_autoboot_default;
447         pos += sizeof(bool);
448
449         *(uint32_t *)pos = __cpu_to_be32(opt->type);
450         pos += 4;
451
452         assert(pos <= buf + buf_len);
453
454         return (pos <= buf + buf_len) ? 0 : -1;
455 }
456
457 int pb_protocol_serialise_boot_command(const struct boot_command *boot,
458                 char *buf, int buf_len)
459 {
460         char *pos = buf;
461
462         pos += pb_protocol_serialise_string(pos, boot->option_id);
463         pos += pb_protocol_serialise_string(pos, boot->boot_image_file);
464         pos += pb_protocol_serialise_string(pos, boot->initrd_file);
465         pos += pb_protocol_serialise_string(pos, boot->dtb_file);
466         pos += pb_protocol_serialise_string(pos, boot->boot_args);
467         pos += pb_protocol_serialise_string(pos, boot->args_sig_file);
468         pos += pb_protocol_serialise_string(pos, boot->console);
469
470         assert(pos <= buf + buf_len);
471
472         return (pos <= buf + buf_len) ? 0 : -1;
473 }
474
475 int pb_protocol_serialise_boot_status(const struct status *status,
476                 char *buf, int buf_len)
477 {
478         char *pos = buf;
479
480         *(uint32_t *)pos = __cpu_to_be32(status->type);
481         pos += sizeof(uint32_t);
482
483         pos += pb_protocol_serialise_string(pos, status->message);
484
485         *(bool *)pos = __cpu_to_be32(status->backlog);
486         pos += sizeof(bool);
487
488         *(bool *)pos = __cpu_to_be32(status->boot_active);
489         pos += sizeof(bool);
490
491         assert(pos <= buf + buf_len);
492
493         return (pos <= buf + buf_len) ? 0 : -1;
494 }
495
496 int pb_protocol_serialise_system_info(const struct system_info *sysinfo,
497                 char *buf, int buf_len)
498 {
499         char *pos = buf;
500         unsigned int i;
501
502         pos += pb_protocol_serialise_string(pos, sysinfo->type);
503         pos += pb_protocol_serialise_string(pos, sysinfo->identifier);
504
505         *(uint32_t *)pos = __cpu_to_be32(sysinfo->n_primary);
506         pos += sizeof(uint32_t);
507         for (i = 0; i < sysinfo->n_primary; i++)
508                 pos += pb_protocol_serialise_string(pos, sysinfo->platform_primary[i]);
509
510         *(uint32_t *)pos = __cpu_to_be32(sysinfo->n_other);
511         pos += sizeof(uint32_t);
512         for (i = 0; i < sysinfo->n_other; i++)
513                 pos += pb_protocol_serialise_string(pos, sysinfo->platform_other[i]);
514
515         *(uint32_t *)pos = __cpu_to_be32(sysinfo->n_bmc_current);
516         pos += sizeof(uint32_t);
517         for (i = 0; i < sysinfo->n_bmc_current; i++)
518                 pos += pb_protocol_serialise_string(pos, sysinfo->bmc_current[i]);
519
520         *(uint32_t *)pos = __cpu_to_be32(sysinfo->n_bmc_golden);
521         pos += sizeof(uint32_t);
522         for (i = 0; i < sysinfo->n_bmc_golden; i++)
523                 pos += pb_protocol_serialise_string(pos, sysinfo->bmc_golden[i]);
524
525         *(uint32_t *)pos = __cpu_to_be32(sysinfo->n_interfaces);
526         pos += sizeof(uint32_t);
527
528         for (i = 0; i < sysinfo->n_interfaces; i++) {
529                 struct interface_info *if_info = sysinfo->interfaces[i];
530
531                 *(uint32_t *)pos = __cpu_to_be32(if_info->hwaddr_size);
532                 pos += sizeof(uint32_t);
533
534                 memcpy(pos, if_info->hwaddr, if_info->hwaddr_size);
535                 pos += if_info->hwaddr_size;
536
537                 pos += pb_protocol_serialise_string(pos, if_info->name);
538
539                 *(bool *)pos = if_info->link;
540                 pos += sizeof(bool);
541
542                 pos += pb_protocol_serialise_string(pos, if_info->address);
543                 pos += pb_protocol_serialise_string(pos, if_info->address_v6);
544         }
545
546         *(uint32_t *)pos = __cpu_to_be32(sysinfo->n_blockdevs);
547         pos += sizeof(uint32_t);
548
549         for (i = 0; i < sysinfo->n_blockdevs; i++) {
550                 struct blockdev_info *bd_info = sysinfo->blockdevs[i];
551
552                 pos += pb_protocol_serialise_string(pos, bd_info->name);
553                 pos += pb_protocol_serialise_string(pos, bd_info->uuid);
554                 pos += pb_protocol_serialise_string(pos, bd_info->mountpoint);
555         }
556
557         if (sysinfo->bmc_mac)
558                 memcpy(pos, sysinfo->bmc_mac, HWADDR_SIZE);
559         else
560                 memset(pos, 0, HWADDR_SIZE);
561         pos += HWADDR_SIZE;
562
563         assert(pos <= buf + buf_len);
564
565         return (pos <= buf + buf_len) ? 0 : -1;
566 }
567
568 static int pb_protocol_serialise_config_interface(char *buf,
569                 struct interface_config *conf)
570 {
571         char *pos = buf;
572
573         memcpy(pos, conf->hwaddr, sizeof(conf->hwaddr));
574         pos += sizeof(conf->hwaddr);
575
576         *(uint32_t *)pos = conf->ignore;
577         pos += 4;
578
579         if (conf->ignore)
580                 return pos - buf;
581
582         *(uint32_t *)pos = __cpu_to_be32(conf->method);
583         pos += 4;
584
585         if (conf->method == CONFIG_METHOD_STATIC) {
586                 pos += pb_protocol_serialise_string(pos,
587                                 conf->static_config.address);
588                 pos += pb_protocol_serialise_string(pos,
589                                 conf->static_config.gateway);
590                 pos += pb_protocol_serialise_string(pos,
591                                 conf->static_config.url);
592         }
593
594         *(uint32_t *)pos = conf->override;
595         pos += 4;
596
597         return pos - buf;
598 }
599
600 int pb_protocol_serialise_config(const struct config *config,
601                 char *buf, int buf_len)
602 {
603         char *pos = buf;
604         unsigned int i;
605
606         *(uint32_t *)pos = config->autoboot_enabled;
607         pos += 4;
608
609         *(uint32_t *)pos = __cpu_to_be32(config->autoboot_timeout_sec);
610         pos += 4;
611
612         *(uint32_t *)pos = config->safe_mode;
613         pos += 4;
614
615         *(uint32_t *)pos = __cpu_to_be32(config->network.n_interfaces);
616         pos += 4;
617         for (i = 0; i < config->network.n_interfaces; i++) {
618                 struct interface_config *iface =
619                         config->network.interfaces[i];
620                 pos += pb_protocol_serialise_config_interface(pos, iface);
621         }
622
623         *(uint32_t *)pos = __cpu_to_be32(config->network.n_dns_servers);
624         pos += 4;
625         for (i = 0; i < config->network.n_dns_servers; i++) {
626                 pos += pb_protocol_serialise_string(pos,
627                                 config->network.dns_servers[i]);
628         }
629
630         pos += pb_protocol_serialise_string(pos, config->http_proxy);
631         pos += pb_protocol_serialise_string(pos, config->https_proxy);
632
633         *(uint32_t *)pos = __cpu_to_be32(config->n_autoboot_opts);
634         pos += 4;
635         for (i = 0; i < config->n_autoboot_opts; i++) {
636                 *(uint32_t *)pos =
637                         __cpu_to_be32(config->autoboot_opts[i].boot_type);
638                 pos += 4;
639                 if (config->autoboot_opts[i].boot_type == BOOT_DEVICE_TYPE) {
640                         *(uint32_t *)pos =
641                                 __cpu_to_be32(config->autoboot_opts[i].type);
642                         pos += 4;
643                 } else {
644                         pos += pb_protocol_serialise_string(pos,
645                                                 config->autoboot_opts[i].uuid);
646                 }
647         }
648
649         *(uint32_t *)pos = __cpu_to_be32(config->ipmi_bootdev);
650         pos += 4;
651         *(uint32_t *)pos = config->ipmi_bootdev_persistent;
652         pos += 4;
653         *(uint32_t *)pos = config->ipmi_bootdev_mailbox;
654         pos += 4;
655
656         *(uint32_t *)pos = config->allow_writes;
657         pos += 4;
658
659         *(uint32_t *)pos = __cpu_to_be32(config->n_consoles);
660         pos += 4;
661         for (i = 0; i < config->n_consoles; i++)
662                 pos += pb_protocol_serialise_string(pos, config->consoles[i]);
663
664         pos += pb_protocol_serialise_string(pos, config->boot_console);
665         *(uint32_t *)pos = config->manual_console;
666         pos += 4;
667
668         pos += pb_protocol_serialise_string(pos, config->lang);
669
670         assert(pos <= buf + buf_len);
671
672         return (pos <= buf + buf_len) ? 0 : -1;
673 }
674
675 int pb_protocol_serialise_url(const char *url, char *buf, int buf_len)
676 {
677         char *pos = buf;
678
679         pos += pb_protocol_serialise_string(pos, url);
680
681         assert(pos <=buf+buf_len);
682
683         return (pos <= buf + buf_len) ? 0 : -1;
684 }
685
686 int pb_protocol_serialise_plugin_option(const struct plugin_option *opt,
687                 char *buf, int buf_len)
688 {
689         char *pos = buf;
690         unsigned int i;
691
692         pos += pb_protocol_serialise_string(pos, opt->id);
693         pos += pb_protocol_serialise_string(pos, opt->name);
694         pos += pb_protocol_serialise_string(pos, opt->vendor);
695         pos += pb_protocol_serialise_string(pos, opt->vendor_id);
696         pos += pb_protocol_serialise_string(pos, opt->version);
697         pos += pb_protocol_serialise_string(pos, opt->date);
698         pos += pb_protocol_serialise_string(pos, opt->plugin_file);
699
700         *(uint32_t *)pos = __cpu_to_be32(opt->n_executables);
701         pos += 4;
702
703         for (i = 0; i < opt->n_executables; i++)
704                 pos += pb_protocol_serialise_string(pos, opt->executables[i]);
705
706         assert(pos <= buf + buf_len);
707
708         return (pos <= buf + buf_len) ? 0 : -1;
709 }
710
711 int pb_protocol_serialise_temp_autoboot(const struct autoboot_option *opt,
712                 char *buf, int buf_len)
713 {
714         char *pos = buf;
715
716         *(uint32_t *)pos = __cpu_to_be32(opt->boot_type);
717         pos += 4;
718
719         if (opt->boot_type == BOOT_DEVICE_TYPE) {
720                 *(uint32_t *)pos = __cpu_to_be32(opt->type);
721                 pos += 4;
722         } else {
723                 pos += pb_protocol_serialise_string(pos, opt->uuid);
724         }
725
726         assert(pos <= buf + buf_len);
727
728         return (pos <= buf + buf_len) ? 0 : -1;
729 }
730
731 int pb_protocol_serialise_authenticate(struct auth_message *msg,
732                 char *buf, int buf_len)
733 {
734         char *pos = buf;
735
736         *(enum auth_msg_type *)pos = msg->op;
737         pos += sizeof(enum auth_msg_type);
738
739         switch(msg->op) {
740         case AUTH_MSG_REQUEST:
741                 pos += pb_protocol_serialise_string(pos, msg->password);
742                 break;
743         case AUTH_MSG_RESPONSE:
744                 *(bool *)pos = msg->authenticated;
745                 pos += sizeof(bool);
746                 break;
747         case AUTH_MSG_SET:
748                 pos += pb_protocol_serialise_string(pos,
749                                 msg->set_password.password);
750                 pos += pb_protocol_serialise_string(pos,
751                                 msg->set_password.new_password);
752                 break;
753         case AUTH_MSG_DECRYPT:
754                 pos += pb_protocol_serialise_string(pos,
755                                 msg->decrypt_dev.password);
756                 pos += pb_protocol_serialise_string(pos,
757                                 msg->decrypt_dev.device_id);
758                 break;
759         default:
760                 pb_log("%s: invalid msg\n", __func__);
761                 return -1;
762         };
763
764         assert(pos <= buf + buf_len);
765
766         return (pos <= buf + buf_len) ? 0 : -1;
767 }
768
769 int pb_protocol_write_message(int fd, struct pb_protocol_message *message)
770 {
771         int total_len, rc;
772         char *pos;
773
774         total_len = sizeof(*message) + message->payload_len;
775
776         message->payload_len = __cpu_to_be32(message->payload_len);
777         message->action = __cpu_to_be32(message->action);
778
779         for (pos = (void *)message; total_len;) {
780                 rc = write(fd, pos, total_len);
781
782                 if (rc <= 0)
783                         break;
784
785                 total_len -= rc;
786                 pos += rc;
787         }
788
789         talloc_free(message);
790
791         if (!total_len)
792                 return 0;
793
794         pb_log_fn("failed: %s\n", strerror(errno));
795         return -1;
796 }
797
798 struct pb_protocol_message *pb_protocol_create_message(void *ctx,
799                 enum pb_protocol_action action, int payload_len)
800 {
801         struct pb_protocol_message *message;
802
803         if (payload_len > PB_PROTOCOL_MAX_PAYLOAD_SIZE) {
804                 pb_log_fn("payload too big %u/%u\n", payload_len,
805                         PB_PROTOCOL_MAX_PAYLOAD_SIZE);
806                 return NULL;
807         }
808
809         message = talloc_size(ctx, sizeof(*message) + payload_len);
810
811         /* we convert these to big-endian in write_message() */
812         message->action = action;
813         message->payload_len = payload_len;
814
815         return message;
816
817 }
818
819 struct pb_protocol_message *pb_protocol_read_message(void *ctx, int fd)
820 {
821         struct pb_protocol_message *message, m;
822         int rc;
823         unsigned int len;
824
825         /* use the stack for the initial 8-byte read */
826
827         rc = read(fd, &m, sizeof(m));
828         if (rc != sizeof(m))
829                 return NULL;
830
831         m.payload_len = __be32_to_cpu(m.payload_len);
832         m.action = __be32_to_cpu(m.action);
833
834         if (m.payload_len > PB_PROTOCOL_MAX_PAYLOAD_SIZE) {
835                 pb_log_fn("payload too big %u/%u\n", m.payload_len,
836                         PB_PROTOCOL_MAX_PAYLOAD_SIZE);
837                 return NULL;
838         }
839
840         message = talloc_size(ctx, sizeof(m) + m.payload_len);
841         memcpy(message, &m, sizeof(m));
842
843         for (len = 0; len < m.payload_len;) {
844                 rc = read(fd, message->payload + len, m.payload_len - len);
845
846                 if (rc <= 0) {
847                         talloc_free(message);
848                         pb_log_fn("failed (%u): %s\n", len,
849                                 strerror(errno));
850                         return NULL;
851                 }
852
853                 len += rc;
854         }
855
856         return message;
857 }
858
859
860 int pb_protocol_deserialise_device(struct device *dev,
861                 const struct pb_protocol_message *message)
862 {
863         unsigned int len;
864         const char *pos;
865         int rc = -1;
866
867         len = message->payload_len;
868         pos = message->payload;
869
870         if (read_string(dev, &pos, &len, &dev->id))
871                 goto out;
872
873         if (len < sizeof(enum device_type))
874                 goto out;
875         dev->type = *(enum device_type *)(pos);
876         pos += sizeof(enum device_type);
877         len -= sizeof(enum device_type);
878
879         if (read_string(dev, &pos, &len, &dev->name))
880                 goto out;
881
882         if (read_string(dev, &pos, &len, &dev->description))
883                 goto out;
884
885         if (read_string(dev, &pos, &len, &dev->icon_file))
886                 goto out;
887
888         rc = 0;
889
890 out:
891         return rc;
892 }
893
894 int pb_protocol_deserialise_boot_option(struct boot_option *opt,
895                 const struct pb_protocol_message *message)
896 {
897         unsigned int len;
898         const char *pos;
899         int rc = -1;
900
901         len = message->payload_len;
902         pos = message->payload;
903
904         if (read_string(opt, &pos, &len, &opt->device_id))
905                 goto out;
906
907         if (read_string(opt, &pos, &len, &opt->id))
908                 goto out;
909
910         if (read_string(opt, &pos, &len, &opt->name))
911                 goto out;
912
913         if (read_string(opt, &pos, &len, &opt->description))
914                 goto out;
915
916         if (read_string(opt, &pos, &len, &opt->icon_file))
917                 goto out;
918
919         if (read_string(opt, &pos, &len, &opt->boot_image_file))
920                 goto out;
921
922         if (read_string(opt, &pos, &len, &opt->initrd_file))
923                 goto out;
924
925         if (read_string(opt, &pos, &len, &opt->dtb_file))
926                 goto out;
927
928         if (read_string(opt, &pos, &len, &opt->boot_args))
929                 goto out;
930
931         if (read_string(opt, &pos, &len, &opt->args_sig_file))
932                 goto out;
933
934         if (len < sizeof(bool))
935                 goto out;
936         opt->is_default = *(bool *)(pos);
937         pos += sizeof(bool);
938         len -= sizeof(bool);
939         opt->is_autoboot_default = *(bool *)(pos);
940         pos += sizeof(bool);
941         len -= sizeof(bool);
942
943         if (read_u32(&pos, &len, &opt->type))
944                 return -1;
945
946         rc = (pos <= message->payload + message->payload_len) ? 0 : -1;
947
948 out:
949         return rc;
950 }
951
952 int pb_protocol_deserialise_boot_command(struct boot_command *cmd,
953                 const struct pb_protocol_message *message)
954 {
955         unsigned int len;
956         const char *pos;
957         int rc = -1;
958
959         len = message->payload_len;
960         pos = message->payload;
961
962         if (read_string(cmd, &pos, &len, &cmd->option_id))
963                 goto out;
964
965         if (read_string(cmd, &pos, &len, &cmd->boot_image_file))
966                 goto out;
967
968         if (read_string(cmd, &pos, &len, &cmd->initrd_file))
969                 goto out;
970
971         if (read_string(cmd, &pos, &len, &cmd->dtb_file))
972                 goto out;
973
974         if (read_string(cmd, &pos, &len, &cmd->boot_args))
975                 goto out;
976
977         if (read_string(cmd, &pos, &len, &cmd->args_sig_file))
978                 goto out;
979
980         if (read_string(cmd, &pos, &len, &cmd->console))
981                 goto out;
982
983         rc = 0;
984
985 out:
986         return rc;
987 }
988
989 int pb_protocol_deserialise_boot_status(struct status *status,
990                 const struct pb_protocol_message *message)
991 {
992         unsigned int len;
993         const char *pos;
994         int rc = -1;
995
996         len = message->payload_len;
997         pos = message->payload;
998
999         /* first up, the type enum... */
1000         if (len < sizeof(uint32_t))
1001                 goto out;
1002
1003         status->type = __be32_to_cpu(*(uint32_t *)(pos));
1004
1005         switch (status->type) {
1006         case STATUS_ERROR:
1007         case STATUS_INFO:
1008                 break;
1009         default:
1010                 goto out;
1011         }
1012
1013         pos += sizeof(uint32_t);
1014         len -= sizeof(uint32_t);
1015
1016         /* message string */
1017         if (read_string(status, &pos, &len, &status->message))
1018                 goto out;
1019
1020         /* backlog */
1021         status->backlog = *(bool *)pos;
1022         pos += sizeof(status->backlog);
1023
1024         /* boot_active */
1025         status->boot_active = *(bool *)pos;
1026         pos += sizeof(status->boot_active);
1027
1028         rc = 0;
1029
1030 out:
1031         return rc;
1032 }
1033
1034 int pb_protocol_deserialise_system_info(struct system_info *sysinfo,
1035                 const struct pb_protocol_message *message)
1036 {
1037         unsigned int len, i;
1038         const char *pos;
1039         int rc = -1;
1040         char *tmp;
1041
1042         len = message->payload_len;
1043         pos = message->payload;
1044
1045         /* type and identifier strings */
1046         if (read_string(sysinfo, &pos, &len, &sysinfo->type))
1047                 goto out;
1048
1049         if (read_string(sysinfo, &pos, &len, &sysinfo->identifier))
1050                 goto out;
1051
1052         /* Platform version strings for openpower platforms */
1053         if (read_u32(&pos, &len, &sysinfo->n_primary))
1054                 goto out;
1055         sysinfo->platform_primary = talloc_array(sysinfo, char *,
1056                                                 sysinfo->n_primary);
1057         for (i = 0; i < sysinfo->n_primary; i++) {
1058                 if (read_string(sysinfo, &pos, &len, &tmp))
1059                         goto out;
1060                 sysinfo->platform_primary[i] = talloc_strdup(sysinfo, tmp);
1061         }
1062
1063         if (read_u32(&pos, &len, &sysinfo->n_other))
1064                 goto out;
1065         sysinfo->platform_other = talloc_array(sysinfo, char *,
1066                                                 sysinfo->n_other);
1067         for (i = 0; i < sysinfo->n_other; i++) {
1068                 if (read_string(sysinfo, &pos, &len, &tmp))
1069                         goto out;
1070                 sysinfo->platform_other[i] = talloc_strdup(sysinfo, tmp);
1071         }
1072
1073         /* BMC version strings for openpower platforms */
1074         if (read_u32(&pos, &len, &sysinfo->n_bmc_current))
1075                 goto out;
1076         sysinfo->bmc_current = talloc_array(sysinfo, char *,
1077                                                 sysinfo->n_bmc_current);
1078         for (i = 0; i < sysinfo->n_bmc_current; i++) {
1079                 if (read_string(sysinfo, &pos, &len, &tmp))
1080                         goto out;
1081                 sysinfo->bmc_current[i] = talloc_strdup(sysinfo, tmp);
1082         }
1083
1084         if (read_u32(&pos, &len, &sysinfo->n_bmc_golden))
1085                 goto out;
1086         sysinfo->bmc_golden = talloc_array(sysinfo, char *,
1087                                                 sysinfo->n_bmc_golden);
1088         for (i = 0; i < sysinfo->n_bmc_golden; i++) {
1089                 if (read_string(sysinfo, &pos, &len, &tmp))
1090                         goto out;
1091                 sysinfo->bmc_golden[i] = talloc_strdup(sysinfo, tmp);
1092         }
1093
1094         /* number of interfaces */
1095         if (read_u32(&pos, &len, &sysinfo->n_interfaces))
1096                 goto out;
1097
1098         sysinfo->interfaces = talloc_array(sysinfo, struct interface_info *,
1099                         sysinfo->n_interfaces);
1100
1101         for (i = 0; i < sysinfo->n_interfaces; i++) {
1102                 struct interface_info *if_info = talloc(sysinfo,
1103                                                         struct interface_info);
1104
1105                 if (read_u32(&pos, &len, &if_info->hwaddr_size))
1106                         goto out;
1107
1108                 if (len < if_info->hwaddr_size)
1109                         goto out;
1110
1111                 if_info->hwaddr = talloc_memdup(if_info, pos,
1112                                                 if_info->hwaddr_size);
1113                 pos += if_info->hwaddr_size;
1114                 len -= if_info->hwaddr_size;
1115
1116                 if (read_string(if_info, &pos, &len, &if_info->name))
1117                         goto out;
1118
1119                 if_info->link = *(bool *)pos;
1120                 pos += sizeof(if_info->link);
1121
1122                 if (read_string(if_info, &pos, &len, &if_info->address))
1123                         goto out;
1124                 if (read_string(if_info, &pos, &len, &if_info->address_v6))
1125                         goto out;
1126
1127                 sysinfo->interfaces[i] = if_info;
1128         }
1129
1130         /* number of interfaces */
1131         if (read_u32(&pos, &len, &sysinfo->n_blockdevs))
1132                 goto out;
1133
1134         sysinfo->blockdevs = talloc_array(sysinfo, struct blockdev_info *,
1135                         sysinfo->n_blockdevs);
1136
1137         for (i = 0; i < sysinfo->n_blockdevs; i++) {
1138                 struct blockdev_info *bd_info = talloc(sysinfo,
1139                                                         struct blockdev_info);
1140
1141                 if (read_string(bd_info, &pos, &len, &bd_info->name))
1142                         goto out;
1143
1144                 if (read_string(bd_info, &pos, &len, &bd_info->uuid))
1145                         goto out;
1146
1147                 if (read_string(bd_info, &pos, &len, &bd_info->mountpoint))
1148                         goto out;
1149
1150                 sysinfo->blockdevs[i] = bd_info;
1151         }
1152
1153         for (i = 0; i < HWADDR_SIZE; i++) {
1154                 if (pos[i] != 0) {
1155                         sysinfo->bmc_mac = talloc_memdup(sysinfo, pos, HWADDR_SIZE);
1156                         break;
1157                 }
1158         }
1159
1160         pos += HWADDR_SIZE;
1161         len -= HWADDR_SIZE;
1162
1163         rc = 0;
1164 out:
1165         return rc;
1166 }
1167
1168 static int pb_protocol_deserialise_config_interface(const char **buf,
1169                 unsigned int *len, struct interface_config *iface)
1170 {
1171         unsigned int tmp;
1172
1173         if (*len < sizeof(iface->hwaddr))
1174                 return -1;
1175
1176         memcpy(iface->hwaddr, *buf, sizeof(iface->hwaddr));
1177         *buf += sizeof(iface->hwaddr);
1178         *len -= sizeof(iface->hwaddr);
1179
1180         if (read_u32(buf, len, &tmp))
1181                 return -1;
1182         iface->ignore = !!tmp;
1183
1184         if (iface->ignore)
1185                 return 0;
1186
1187         if (read_u32(buf, len, &iface->method))
1188                 return -1;
1189
1190         if (iface->method == CONFIG_METHOD_STATIC) {
1191                 if (read_string(iface, buf, len, &iface->static_config.address))
1192                         return -1;
1193
1194                 if (read_string(iface, buf, len, &iface->static_config.gateway))
1195                         return -1;
1196
1197                 if (read_string(iface, buf, len, &iface->static_config.url))
1198                         return -1;
1199         }
1200
1201         if (read_u32(buf, len, &tmp))
1202                 return -1;
1203         iface->override = !!tmp;
1204
1205         return 0;
1206 }
1207
1208 int pb_protocol_deserialise_config(struct config *config,
1209                 const struct pb_protocol_message *message)
1210 {
1211         unsigned int len, i, tmp;
1212         const char *pos;
1213         int rc = -1;
1214         char *str;
1215
1216         len = message->payload_len;
1217         pos = message->payload;
1218
1219         if (read_u32(&pos, &len, &tmp))
1220                 goto out;
1221         config->autoboot_enabled = !!tmp;
1222
1223         if (read_u32(&pos, &len, &config->autoboot_timeout_sec))
1224                 goto out;
1225
1226         if (read_u32(&pos, &len, &tmp))
1227                 goto out;
1228         config->safe_mode = !!tmp;
1229
1230         if (read_u32(&pos, &len, &config->network.n_interfaces))
1231                 goto out;
1232
1233         config->network.interfaces = talloc_array(config,
1234                         struct interface_config *, config->network.n_interfaces);
1235
1236         for (i = 0; i < config->network.n_interfaces; i++) {
1237                 struct interface_config *iface = talloc_zero(
1238                                 config->network.interfaces,
1239                                 struct interface_config);
1240                 if (pb_protocol_deserialise_config_interface(&pos, &len, iface))
1241                         goto out;
1242                 config->network.interfaces[i] = iface;
1243         }
1244
1245         if (read_u32(&pos, &len, &config->network.n_dns_servers))
1246                 goto out;
1247         config->network.dns_servers = talloc_array(config, const char *,
1248                         config->network.n_dns_servers);
1249
1250         for (i = 0; i < config->network.n_dns_servers; i++) {
1251                 if (read_string(config->network.dns_servers, &pos, &len, &str))
1252                         goto out;
1253                 config->network.dns_servers[i] = str;
1254         }
1255
1256         if (read_string(config, &pos, &len, &str))
1257                 goto out;
1258         config->http_proxy = str;
1259         if (read_string(config, &pos, &len, &str))
1260                 goto out;
1261         config->https_proxy = str;
1262
1263         if (read_u32(&pos, &len, &config->n_autoboot_opts))
1264                 goto out;
1265         config->autoboot_opts = talloc_array(config, struct autoboot_option,
1266                         config->n_autoboot_opts);
1267
1268         for (i = 0; i < config->n_autoboot_opts; i++) {
1269                 if (read_u32(&pos, &len, &tmp))
1270                         goto out;
1271                 config->autoboot_opts[i].boot_type = (int)tmp;
1272                 if (config->autoboot_opts[i].boot_type == BOOT_DEVICE_TYPE) {
1273                         if (read_u32(&pos, &len, &tmp))
1274                                 goto out;
1275                         config->autoboot_opts[i].type = tmp;
1276                 } else {
1277                         if (read_string(config, &pos, &len, &str))
1278                                 goto out;
1279                         config->autoboot_opts[i].uuid = str;
1280                 }
1281         }
1282
1283         if (read_u32(&pos, &len, &config->ipmi_bootdev))
1284                 goto out;
1285         if (read_u32(&pos, &len, &tmp))
1286                 goto out;
1287         config->ipmi_bootdev_persistent = !!tmp;
1288         if (read_u32(&pos, &len, &tmp))
1289                 goto out;
1290         config->ipmi_bootdev_mailbox = !!tmp;
1291
1292         if (read_u32(&pos, &len, &tmp))
1293                 goto out;
1294         config->allow_writes = !!tmp;
1295
1296         if (read_u32(&pos, &len, &config->n_consoles))
1297                 goto out;
1298
1299         config->consoles = talloc_array(config, char *, config->n_consoles);
1300         for (i = 0; i < config->n_consoles; i++) {
1301                 if (read_string(config->consoles, &pos, &len, &str))
1302                         goto out;
1303                 config->consoles[i] = str;
1304         }
1305
1306         if (read_string(config, &pos, &len, &str))
1307                 goto out;
1308
1309         config->boot_console = str;
1310
1311         if (read_u32(&pos, &len, &tmp))
1312                 goto out;
1313         config->manual_console = !!tmp;
1314
1315         if (read_string(config, &pos, &len, &str))
1316                 goto out;
1317
1318         config->lang = str;
1319
1320         rc = 0;
1321
1322 out:
1323         return rc;
1324 }
1325
1326 int pb_protocol_deserialise_plugin_option(struct plugin_option *opt,
1327                 const struct pb_protocol_message *message)
1328 {
1329         unsigned int len, i, tmp;
1330         const char *pos;
1331         int rc = -1;
1332         char *str;
1333
1334         len = message->payload_len;
1335         pos = message->payload;
1336
1337         if (read_string(opt, &pos, &len, &str))
1338                 goto out;
1339         opt->id = str;
1340
1341         if (read_string(opt, &pos, &len, &str))
1342                 goto out;
1343         opt->name = str;
1344
1345         if (read_string(opt, &pos, &len, &str))
1346                 goto out;
1347         opt->vendor = str;
1348
1349         if (read_string(opt, &pos, &len, &str))
1350                 goto out;
1351         opt->vendor_id = str;
1352
1353         if (read_string(opt, &pos, &len, &str))
1354                 goto out;
1355         opt->version = str;
1356
1357         if (read_string(opt, &pos, &len, &str))
1358                 goto out;
1359         opt->date = str;
1360
1361         if (read_string(opt, &pos, &len, &str))
1362                 goto out;
1363         opt->plugin_file = str;
1364
1365         if (read_u32(&pos, &len, &tmp))
1366                 goto out;
1367         opt->n_executables = tmp;
1368
1369         opt->executables = talloc_zero_array(opt, char *, opt->n_executables);
1370         if (!opt->executables)
1371                 goto out;
1372
1373         for (i = 0; i < opt->n_executables; i++) {
1374                 if (read_string(opt, &pos, &len, &str))
1375                         goto out;
1376                 opt->executables[i] = talloc_strdup(opt, str);
1377         }
1378
1379         rc = 0;
1380 out:
1381         return rc;
1382 }
1383
1384 int pb_protocol_deserialise_temp_autoboot(struct autoboot_option *opt,
1385                 const struct pb_protocol_message *message)
1386 {
1387         unsigned int len, tmp;
1388         const char *pos;
1389         int rc = -1;
1390         char *str;
1391
1392         len = message->payload_len;
1393         pos = message->payload;
1394
1395         if (read_u32(&pos, &len, &tmp))
1396                 goto out;
1397
1398         opt->boot_type = tmp;
1399         if (opt->boot_type == BOOT_DEVICE_TYPE) {
1400                 if (read_u32(&pos, &len, &tmp))
1401                         goto out;
1402                 opt->type = tmp;
1403
1404         } else if (opt->boot_type == BOOT_DEVICE_UUID) {
1405                 if (read_string(opt, &pos, &len, &str))
1406                         goto out;
1407                 opt->uuid = str;
1408
1409         } else {
1410                 return -1;
1411         }
1412
1413         rc = 0;
1414
1415 out:
1416         return rc;
1417 }
1418
1419 int pb_protocol_deserialise_authenticate(struct auth_message *msg,
1420                 const struct pb_protocol_message *message)
1421 {
1422         unsigned int len;
1423         const char *pos;
1424
1425         len = message->payload_len;
1426         pos = message->payload;
1427
1428         msg->op = *(enum auth_msg_type *)pos;
1429         pos += sizeof(enum auth_msg_type);
1430
1431         switch (msg->op) {
1432         case AUTH_MSG_REQUEST:
1433                 if (read_string(msg, &pos, &len, &msg->password))
1434                         return -1;
1435                 break;
1436         case AUTH_MSG_RESPONSE:
1437                 msg->authenticated = *(bool *)pos;
1438                 pos += sizeof(bool);
1439                 break;
1440         case AUTH_MSG_SET:
1441                 if (read_string(msg, &pos, &len, &msg->set_password.password))
1442                         return -1;
1443                 if (read_string(msg, &pos, &len,
1444                                         &msg->set_password.new_password))
1445                         return -1;
1446                 break;
1447         case AUTH_MSG_DECRYPT:
1448                 if (read_string(msg, &pos, &len, &msg->decrypt_dev.password))
1449                         return -1;
1450                 if (read_string(msg, &pos, &len,
1451                                         &msg->decrypt_dev.device_id))
1452                         return -1;
1453                 break;
1454         default:
1455                 pb_log("%s: unable to parse\n", __func__);
1456                 return -1;
1457         }
1458
1459         return 0;
1460 }