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