]> git.ozlabs.org Git - petitboot/blob - discover/device-handler.c
utils: Add helper to send mailbox request
[petitboot] / discover / device-handler.c
1 #include <assert.h>
2 #include <inttypes.h>
3 #include <stdlib.h>
4 #include <stdbool.h>
5 #include <unistd.h>
6 #include <string.h>
7 #include <errno.h>
8 #include <mntent.h>
9 #include <locale.h>
10 #include <sys/stat.h>
11 #include <sys/wait.h>
12 #include <sys/mount.h>
13
14 #include <talloc/talloc.h>
15 #include <list/list.h>
16 #include <log/log.h>
17 #include <types/types.h>
18 #include <system/system.h>
19 #include <process/process.h>
20 #include <url/url.h>
21 #include <i18n/i18n.h>
22 #include <pb-config/pb-config.h>
23
24 #include <sys/sysmacros.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <netdb.h>
28 #include <arpa/inet.h>
29
30 #include "device-handler.h"
31 #include "discover-server.h"
32 #include "devmapper.h"
33 #include "user-event.h"
34 #include "platform.h"
35 #include "event.h"
36 #include "parser.h"
37 #include "resource.h"
38 #include "paths.h"
39 #include "sysinfo.h"
40 #include "boot.h"
41 #include "udev.h"
42 #include "network.h"
43 #include "ipmi.h"
44
45 enum default_priority {
46         DEFAULT_PRIORITY_TEMP_USER      = 1,
47         DEFAULT_PRIORITY_REMOTE         = 2,
48         DEFAULT_PRIORITY_LOCAL_FIRST    = 3,
49         DEFAULT_PRIORITY_LOCAL_LAST     = 0xfe,
50         DEFAULT_PRIORITY_DISABLED       = 0xff,
51 };
52
53 static int default_rescan_timeout = 5 * 60; /* seconds */
54
55 struct progress_info {
56         unsigned int                    percentage;
57         unsigned long                   size;           /* size in bytes */
58
59         const struct process_info       *procinfo;
60         struct list_item        list;
61 };
62
63 struct device_handler {
64         struct discover_server  *server;
65         int                     dry_run;
66
67         struct pb_udev          *udev;
68         struct network          *network;
69         struct user_event       *user_event;
70
71         struct discover_device  **devices;
72         unsigned int            n_devices;
73
74         struct ramdisk_device   **ramdisks;
75         unsigned int            n_ramdisks;
76
77         struct waitset          *waitset;
78         struct waiter           *timeout_waiter;
79         bool                    autoboot_enabled;
80         unsigned int            sec_to_boot;
81         struct autoboot_option  *temp_autoboot;
82
83         struct discover_boot_option *default_boot_option;
84         struct discover_boot_option *last_boot_option;
85         int                     default_boot_option_priority;
86
87         struct list             unresolved_boot_options;
88
89         struct boot_task        *pending_boot;
90         bool                    pending_boot_is_default;
91
92         struct list             progress;
93         unsigned int            n_progress;
94
95         struct plugin_option    **plugins;
96         unsigned int            n_plugins;
97         bool                    plugin_installing;
98 };
99
100 static int mount_device(struct discover_device *dev);
101 static int umount_device(struct discover_device *dev);
102
103 static int device_handler_init_sources(struct device_handler *handler);
104 static void device_handler_reinit_sources(struct device_handler *handler);
105
106 static void device_handler_update_lang(const char *lang);
107
108 void discover_context_add_boot_option(struct discover_context *ctx,
109                 struct discover_boot_option *boot_option)
110 {
111         boot_option->source = ctx->parser;
112         list_add_tail(&ctx->boot_options, &boot_option->list);
113         talloc_steal(ctx, boot_option);
114 }
115
116 /**
117  * device_handler_get_device_count - Get the count of current handler devices.
118  */
119
120 int device_handler_get_device_count(const struct device_handler *handler)
121 {
122         return handler->n_devices;
123 }
124
125 /**
126  * device_handler_get_device - Get a handler device by index.
127  */
128
129 const struct discover_device *device_handler_get_device(
130         const struct device_handler *handler, unsigned int index)
131 {
132         if (index >= handler->n_devices) {
133                 assert(0 && "bad index");
134                 return NULL;
135         }
136
137         return handler->devices[index];
138 }
139
140 /**
141  * device_handler_get_plugin_count - Get the count of current handler plugins.
142  */
143 int device_handler_get_plugin_count(const struct device_handler *handler)
144 {
145         return handler->n_plugins;
146 }
147
148 /**
149  * discover_handler_get_plugin - Get a handler plugin by index.
150  */
151 const struct plugin_option *device_handler_get_plugin(
152         const struct device_handler *handler, unsigned int index)
153 {
154         if (index >= handler->n_plugins) {
155                 assert(0 && "bad index");
156                 return NULL;
157         }
158
159         return handler->plugins[index];
160 }
161
162 struct network *device_handler_get_network(
163                 const struct device_handler *handler)
164 {
165         return handler->network;
166 }
167
168 struct discover_boot_option *discover_boot_option_create(
169                 struct discover_context *ctx,
170                 struct discover_device *device)
171 {
172         struct discover_boot_option *opt;
173
174         opt = talloc_zero(ctx, struct discover_boot_option);
175         opt->option = talloc_zero(opt, struct boot_option);
176         opt->device = device;
177
178         return opt;
179 }
180
181 static int device_match_uuid(struct discover_device *dev, const char *uuid)
182 {
183         return dev->uuid && !strcmp(dev->uuid, uuid);
184 }
185
186 static int device_match_label(struct discover_device *dev, const char *label)
187 {
188         return dev->label && !strcmp(dev->label, label);
189 }
190
191 static int device_match_id(struct discover_device *dev, const char *id)
192 {
193         return !strcmp(dev->device->id, id);
194 }
195
196 static int device_match_serial(struct discover_device *dev, const char *serial)
197 {
198         const char *val = discover_device_get_param(dev, "ID_SERIAL");
199         return val && !strcmp(val, serial);
200 }
201
202 static struct discover_device *device_lookup(
203                 struct device_handler *device_handler,
204                 int (match_fn)(struct discover_device *, const char *),
205                 const char *str)
206 {
207         struct discover_device *dev;
208         unsigned int i;
209
210         if (!str)
211                 return NULL;
212
213         for (i = 0; i < device_handler->n_devices; i++) {
214                 dev = device_handler->devices[i];
215
216                 if (match_fn(dev, str))
217                         return dev;
218         }
219
220         return NULL;
221 }
222
223 struct discover_device *device_lookup_by_name(struct device_handler *handler,
224                 const char *name)
225 {
226         if (!strncmp(name, "/dev/", strlen("/dev/")))
227                 name += strlen("/dev/");
228
229         return device_lookup_by_id(handler, name);
230 }
231
232 struct discover_device *device_lookup_by_uuid(
233                 struct device_handler *device_handler,
234                 const char *uuid)
235 {
236         return device_lookup(device_handler, device_match_uuid, uuid);
237 }
238
239 struct discover_device *device_lookup_by_label(
240                 struct device_handler *device_handler,
241                 const char *label)
242 {
243         return device_lookup(device_handler, device_match_label, label);
244 }
245
246 struct discover_device *device_lookup_by_id(
247                 struct device_handler *device_handler,
248                 const char *id)
249 {
250         return device_lookup(device_handler, device_match_id, id);
251 }
252
253 struct discover_device *device_lookup_by_serial(
254                 struct device_handler *device_handler,
255                 const char *serial)
256 {
257         return device_lookup(device_handler, device_match_serial, serial);
258 }
259
260 void device_handler_destroy(struct device_handler *handler)
261 {
262         talloc_free(handler);
263 }
264
265 static int destroy_device(void *arg)
266 {
267         struct discover_device *dev = arg;
268
269         umount_device(dev);
270
271         return 0;
272 }
273
274 struct discover_device *discover_device_create(struct device_handler *handler,
275                 const char *uuid, const char *id)
276 {
277         struct discover_device *dev;
278
279         if (uuid)
280                 dev = device_lookup_by_uuid(handler, uuid);
281         else
282                 dev = device_lookup_by_id(handler, id);
283
284         if (dev)
285                 return dev;
286
287         dev = talloc_zero(handler, struct discover_device);
288         dev->device = talloc_zero(dev, struct device);
289         dev->device->id = talloc_strdup(dev->device, id);
290         dev->uuid = talloc_strdup(dev, uuid);
291         list_init(&dev->params);
292         list_init(&dev->boot_options);
293
294         talloc_set_destructor(dev, destroy_device);
295
296         return dev;
297 }
298
299 struct discover_device_param {
300         char                    *name;
301         char                    *value;
302         struct list_item        list;
303 };
304
305 void discover_device_set_param(struct discover_device *device,
306                 const char *name, const char *value)
307 {
308         struct discover_device_param *param;
309         bool found = false;
310
311         list_for_each_entry(&device->params, param, list) {
312                 if (!strcmp(param->name, name)) {
313                         found = true;
314                         break;
315                 }
316         }
317
318         if (!found) {
319                 if (!value)
320                         return;
321                 param = talloc(device, struct discover_device_param);
322                 param->name = talloc_strdup(param, name);
323                 list_add(&device->params, &param->list);
324         } else {
325                 if (!value) {
326                         list_remove(&param->list);
327                         talloc_free(param);
328                         return;
329                 }
330                 talloc_free(param->value);
331         }
332
333         param->value = talloc_strdup(param, value);
334 }
335
336 const char *discover_device_get_param(struct discover_device *device,
337                 const char *name)
338 {
339         struct discover_device_param *param;
340
341         list_for_each_entry(&device->params, param, list) {
342                 if (!strcmp(param->name, name))
343                         return param->value;
344         }
345         return NULL;
346 }
347
348 static void set_env_variables(const struct config *config)
349 {
350         if (config->http_proxy)
351                 setenv("http_proxy", config->http_proxy, 1);
352         else
353                 unsetenv("http_proxy");
354
355         if (config->https_proxy)
356                 setenv("https_proxy", config->https_proxy, 1);
357         else
358                 unsetenv("https_proxy");
359
360         /* Reduce noise in the log from LVM listing open file descriptors */
361         setenv("LVM_SUPPRESS_FD_WARNINGS", "1", 1);
362 }
363
364 struct device_handler *device_handler_init(struct discover_server *server,
365                 struct waitset *waitset, int dry_run)
366 {
367         struct device_handler *handler;
368         int rc;
369
370         handler = talloc_zero(NULL, struct device_handler);
371         handler->server = server;
372         handler->waitset = waitset;
373         handler->dry_run = dry_run;
374         handler->autoboot_enabled = config_autoboot_active(config_get());
375
376         list_init(&handler->unresolved_boot_options);
377
378         list_init(&handler->progress);
379
380         /* set up our mount point base */
381         pb_mkdir_recursive(mount_base());
382
383         parser_init();
384
385         if (config_get()->safe_mode)
386                 return handler;
387
388         set_env_variables(config_get());
389
390         rc = device_handler_init_sources(handler);
391         if (rc) {
392                 talloc_free(handler);
393                 return NULL;
394         }
395
396         return handler;
397 }
398
399 void device_handler_reinit(struct device_handler *handler)
400 {
401         struct discover_boot_option *opt, *tmp;
402         struct ramdisk_device *ramdisk;
403         struct config *config;
404         unsigned int i;
405
406         device_handler_cancel_default(handler);
407         /* Cancel any pending non-default boot */
408         if (handler->pending_boot) {
409                 boot_cancel(handler->pending_boot);
410                 handler->pending_boot = NULL;
411                 handler->pending_boot_is_default = false;
412         }
413
414         /* Cancel any remaining async jobs */
415         process_stop_async_all();
416         pending_network_jobs_cancel();
417
418         /* free unresolved boot options */
419         list_for_each_entry_safe(&handler->unresolved_boot_options,
420                         opt, tmp, list)
421                 talloc_free(opt);
422         list_init(&handler->unresolved_boot_options);
423
424         /* drop all devices */
425         for (i = 0; i < handler->n_devices; i++) {
426                 struct discover_device *device = handler->devices[i];
427                 discover_server_notify_device_remove(handler->server,
428                                 device->device);
429                 ramdisk = device->ramdisk;
430                 if (device->requery_waiter)
431                         waiter_remove(device->requery_waiter);
432                 talloc_free(device);
433                 talloc_free(ramdisk);
434         }
435
436         talloc_free(handler->devices);
437         handler->devices = NULL;
438         handler->n_devices = 0;
439         talloc_free(handler->ramdisks);
440         handler->ramdisks = NULL;
441         handler->n_ramdisks = 0;
442
443         /* drop any known plugins */
444         for (i = 0; i < handler->n_plugins; i++)
445                 talloc_free(handler->plugins[i]);
446         talloc_free(handler->plugins);
447         handler->plugins = NULL;
448         handler->n_plugins = 0;
449
450         discover_server_notify_plugins_remove(handler->server);
451
452         set_env_variables(config_get());
453
454         /* If the safe mode warning was active disable it now */
455         if (config_get()->safe_mode) {
456                 config = config_copy(handler, config_get());
457                 config->safe_mode = false;
458                 config_set(config);
459                 discover_server_notify_config(handler->server, config);
460         }
461
462         /* Force rediscovery on SCSI devices */
463         process_run_simple(handler, pb_system_apps.scsi_rescan, NULL);
464
465         device_handler_reinit_sources(handler);
466 }
467
468 void device_handler_remove(struct device_handler *handler,
469                 struct discover_device *device)
470 {
471         struct discover_boot_option *opt, *tmp;
472         unsigned int i;
473
474         if (device->requery_waiter)
475                 waiter_remove(device->requery_waiter);
476
477         list_for_each_entry_safe(&device->boot_options, opt, tmp, list) {
478                 if (opt == handler->default_boot_option) {
479                         pb_log("Default option %s cancelled since device removed",
480                                         opt->option->name);
481                         device_handler_cancel_default(handler);
482                         break;
483                 }
484         }
485
486         for (i = 0; i < handler->n_devices; i++)
487                 if (handler->devices[i] == device)
488                         break;
489
490         if (i == handler->n_devices) {
491                 talloc_free(device);
492                 return;
493         }
494
495         /* Free any unresolved options, as they're currently allocated
496          * against the handler */
497         list_for_each_entry_safe(&handler->unresolved_boot_options,
498                         opt, tmp, list) {
499                 if (opt->device != device)
500                         continue;
501                 list_remove(&opt->list);
502                 talloc_free(opt);
503         }
504
505         /* if this is a network device, we have to unregister it from the
506          * network code */
507         if (device->device->type == DEVICE_TYPE_NETWORK)
508                 network_unregister_device(handler->network, device);
509
510         handler->n_devices--;
511         memmove(&handler->devices[i], &handler->devices[i + 1],
512                 (handler->n_devices - i) * sizeof(handler->devices[0]));
513         handler->devices = talloc_realloc(handler, handler->devices,
514                 struct discover_device *, handler->n_devices);
515
516         if (device->notified)
517                 discover_server_notify_device_remove(handler->server,
518                                                         device->device);
519
520         talloc_free(device);
521 }
522
523 void device_handler_status(struct device_handler *handler,
524                 struct status *status)
525 {
526         pb_debug("%s: %s\n", __func__, status->message);
527         discover_server_notify_boot_status(handler->server, status);
528 }
529
530 static void _device_handler_vstatus(struct device_handler *handler,
531                 enum status_type type, const char *fmt, va_list ap)
532 {
533         struct status status;
534
535         status.type = type;
536         status.message = talloc_vasprintf(handler, fmt, ap);
537         status.backlog = false;
538         status.boot_active = false;
539
540         device_handler_status(handler, &status);
541
542         talloc_free(status.message);
543 }
544
545 static void _device_handler_vdevstatus(struct device_handler *handler,
546                 struct discover_device *device, enum status_type type,
547                 const char *fmt, va_list ap)
548 {
549         char *msg;
550
551         msg = talloc_asprintf(handler, "[%s] %s",
552                         device ? device->device->id : "unknown", fmt);
553         _device_handler_vstatus(handler, type, msg, ap);
554         talloc_free(msg);
555 }
556
557 void device_handler_status_dev_info(struct device_handler *handler,
558                 struct discover_device *dev, const char *fmt, ...)
559 {
560         va_list ap;
561
562         va_start(ap, fmt);
563         _device_handler_vdevstatus(handler, dev, STATUS_INFO, fmt, ap);
564         va_end(ap);
565 }
566
567 void device_handler_status_dev_err(struct device_handler *handler,
568                 struct discover_device *dev, const char *fmt, ...)
569 {
570         va_list ap;
571
572         va_start(ap, fmt);
573         _device_handler_vdevstatus(handler, dev, STATUS_ERROR, fmt, ap);
574         va_end(ap);
575 }
576
577 void device_handler_status_info(struct device_handler *handler,
578                 const char *fmt, ...)
579 {
580         va_list ap;
581
582         va_start(ap, fmt);
583         _device_handler_vstatus(handler, STATUS_INFO, fmt, ap);
584         va_end(ap);
585 }
586
587 void device_handler_status_err(struct device_handler *handler,
588                 const char *fmt, ...)
589 {
590         va_list ap;
591
592         va_start(ap, fmt);
593         _device_handler_vstatus(handler, STATUS_ERROR, fmt, ap);
594         va_end(ap);
595 }
596
597 void device_handler_status_download(struct device_handler *handler,
598                 const struct process_info *procinfo,
599                 unsigned int percentage, unsigned int size, char suffix)
600 {
601         struct progress_info *p, *progress = NULL;
602         uint64_t current_converted, current = 0;
603         const char *units = " kMGTP";
604         unsigned long size_bytes;
605         char *update = NULL;
606         double total = 0;
607         unsigned int i;
608         int unit = 0;
609
610         list_for_each_entry(&handler->progress, p, list)
611                 if (p->procinfo == procinfo)
612                         progress = p;
613
614         if (!progress) {
615                 pb_log("Registering new progress struct\n");
616                 progress = talloc_zero(handler, struct progress_info);
617                 if (!progress) {
618                         pb_log("Failed to allocate room for progress struct\n");
619                         return;
620                 }
621                 progress->procinfo = procinfo;
622                 list_add(&handler->progress, &progress->list);
623                 handler->n_progress++;
624         }
625
626         size_bytes = size;
627         for (i = 0; i < strlen(units); i++) {
628                 if (units[i] == suffix)
629                         break;
630         }
631
632         if (i >= strlen(units)) {
633             pb_log("Couldn't recognise suffix '%c'\n", suffix);
634             size_bytes = 0;
635         } else {
636                 while (i--)
637                         size_bytes <<= 10;
638         }
639
640         progress->percentage = percentage;
641         progress->size = size_bytes;
642
643         /*
644          * Aggregate the info we have and update status. If a progress struct
645          * has zero for both percentage and size we assume progress information
646          * is unavailable and fall back to a generic progress message.
647          */
648         list_for_each_entry(&handler->progress, p, list) {
649                 uint64_t c;
650                 double t;
651                 if (!p->percentage || !p->size) {
652                         update = talloc_asprintf(handler,
653                                         _("%u downloads in progress..."),
654                                         handler->n_progress);
655                         current = total = 0;
656                         break;
657                 }
658
659                 c = p->size;
660                 t = (100 * c) / p->percentage;
661
662                 current += c;
663                 total += t;
664         }
665
666         if (total) {
667                 current_converted = current;
668                 while (current_converted >= 1000) {
669                         current_converted >>= 10;
670                         unit++;
671                 }
672                 update = talloc_asprintf(handler,
673                                 _("%u %s downloading: %.0f%% - %" PRIu64 "%cB"),
674                                 handler->n_progress,
675                                 ngettext("item", "items", handler->n_progress),
676                                 (current / total) * 100, current_converted,
677                                 units[unit]);
678         }
679
680         if (!update) {
681                 pb_log_fn("failed to allocate new status\n");
682         } else {
683                 device_handler_status_info(handler, "%s\n", update);
684                 talloc_free(update);
685         }
686 }
687
688 static void device_handler_plugin_scan_device(struct device_handler *handler,
689                 struct discover_device *dev)
690 {
691         int rc;
692
693         pb_debug("Scanning %s for plugin files\n", dev->device->id);
694
695         rc = process_run_simple(handler, pb_system_apps.pb_plugin,
696                                 "scan", dev->mount_path,
697                                 NULL);
698         if (rc)
699                 pb_log("Error from pb-plugin scan %s\n",
700                                 dev->mount_path);
701 }
702
703 void device_handler_status_download_remove(struct device_handler *handler,
704                 struct process_info *procinfo)
705 {
706         struct progress_info *p, *tmp;
707
708         list_for_each_entry_safe(&handler->progress, p, tmp, list)
709                 if (p->procinfo == procinfo) {
710                         list_remove(&p->list);
711                         talloc_free(p);
712                         handler->n_progress--;
713                 }
714 }
715
716 static void device_handler_boot_status_cb(void *arg, struct status *status)
717 {
718         struct device_handler *handler = arg;
719
720         /* boot had failed; update handler state to allow a new default if one
721          * is found later
722          */
723         if (status->type == STATUS_ERROR) {
724                 handler->pending_boot = NULL;
725                 handler->default_boot_option = NULL;
726         }
727
728         device_handler_status(handler, status);
729 }
730
731 static void countdown_status(struct device_handler *handler,
732                 struct discover_boot_option *opt, unsigned int sec)
733 {
734         struct status status;
735
736         status.type = STATUS_INFO;
737         status.message = talloc_asprintf(handler,
738                         _("Booting in %d sec: [%s] %s"), sec,
739                         opt->device->device->id, opt->option->name);
740         status.backlog = false;
741
742         device_handler_status(handler, &status);
743
744         talloc_free(status.message);
745 }
746
747 static int default_timeout(void *arg)
748 {
749         struct device_handler *handler = arg;
750         struct discover_boot_option *opt;
751
752         if (!handler->default_boot_option)
753                 return 0;
754
755         if (handler->pending_boot)
756                 return 0;
757
758         opt = handler->default_boot_option;
759
760         handler->last_boot_option = opt;
761
762         if (handler->sec_to_boot) {
763                 countdown_status(handler, opt, handler->sec_to_boot);
764                 handler->sec_to_boot--;
765                 handler->timeout_waiter = waiter_register_timeout(
766                                                 handler->waitset, 1000,
767                                                 default_timeout, handler);
768                 return 0;
769         }
770
771         handler->timeout_waiter = NULL;
772
773         pb_log("Timeout expired, booting default option %s\n", opt->option->id);
774
775         platform_pre_boot();
776
777         handler->pending_boot = boot(handler, handler->default_boot_option,
778                         NULL, handler->dry_run, device_handler_boot_status_cb,
779                         handler);
780         handler->pending_boot_is_default = true;
781         return 0;
782 }
783
784 struct {
785         enum ipmi_bootdev       ipmi_type;
786         enum device_type        device_type;
787 } device_type_map[] = {
788         { IPMI_BOOTDEV_NETWORK, DEVICE_TYPE_NETWORK },
789         { IPMI_BOOTDEV_DISK, DEVICE_TYPE_DISK },
790         { IPMI_BOOTDEV_DISK, DEVICE_TYPE_USB },
791         { IPMI_BOOTDEV_CDROM, DEVICE_TYPE_OPTICAL },
792 };
793
794 static bool ipmi_device_type_matches(enum ipmi_bootdev ipmi_type,
795                 enum device_type device_type)
796 {
797         unsigned int i;
798
799         for (i = 0; i < ARRAY_SIZE(device_type_map); i++) {
800                 if (device_type_map[i].device_type == device_type)
801                         return device_type_map[i].ipmi_type == ipmi_type;
802         }
803
804         return false;
805 }
806
807 static bool autoboot_option_matches(struct autoboot_option *opt,
808                 struct discover_device *dev)
809 {
810         if (opt->boot_type == BOOT_DEVICE_UUID)
811                 if (!strcmp(opt->uuid, dev->uuid))
812                         return true;
813
814         if (opt->boot_type == BOOT_DEVICE_TYPE)
815                 if (opt->type == dev->device->type ||
816                     opt->type == DEVICE_TYPE_ANY)
817                         return true;
818
819         return false;
820 }
821
822 static int autoboot_option_priority(const struct config *config,
823                                 struct discover_boot_option *opt)
824 {
825         struct autoboot_option *auto_opt;
826         unsigned int i;
827
828         for (i = 0; i < config->n_autoboot_opts; i++) {
829                 auto_opt = &config->autoboot_opts[i];
830                 if (autoboot_option_matches(auto_opt, opt->device))
831                         return DEFAULT_PRIORITY_LOCAL_FIRST + i;
832         }
833
834         return -1;
835 }
836
837 /*
838  * We have different priorities to resolve conflicts between boot options that
839  * report to be the default for their device. This function assigns a priority
840  * for these options.
841  */
842 static enum default_priority default_option_priority(
843                 struct device_handler *handler,
844                 struct discover_boot_option *opt)
845 {
846         const struct config *config;
847
848         /* Temporary user-provided autoboot options have highest priority */
849         if (handler->temp_autoboot) {
850                 if (autoboot_option_matches(handler->temp_autoboot,
851                                         opt->device))
852                         return DEFAULT_PRIORITY_TEMP_USER;
853
854                 pb_debug("handler: disabled default priority due to "
855                                 "temporary user override\n");
856                 return DEFAULT_PRIORITY_DISABLED;
857         }
858
859         config = config_get();
860
861         /* Next highest priority to IPMI-configured boot options. If we have an
862          * IPMI bootdev configuration set, then we don't allow any other
863          * defaults */
864         if (config->ipmi_bootdev) {
865                 bool ipmi_match = ipmi_device_type_matches(config->ipmi_bootdev,
866                                 opt->device->device->type);
867                 if (ipmi_match)
868                         return DEFAULT_PRIORITY_REMOTE;
869
870                 pb_debug("handler: disabled default priority due to "
871                                 "non-matching IPMI type %x\n",
872                                 config->ipmi_bootdev);
873                 return DEFAULT_PRIORITY_DISABLED;
874         }
875
876         /* Next, try to match the option against the user-defined autoboot
877          * options, either by device UUID or type. */
878         if (config->n_autoboot_opts) {
879                 int boot_match = autoboot_option_priority(config, opt);
880                 if (boot_match > 0)
881                         return boot_match;
882         } else {
883                 /* If there is no specific boot order, boot any device */
884                 return DEFAULT_PRIORITY_LOCAL_FIRST;
885         }
886
887         /* If the option didn't match any entry in the array, it is disabled */
888         pb_debug("handler: disabled default priority due to "
889                         "non-matching UUID or type\n");
890         return DEFAULT_PRIORITY_DISABLED;
891 }
892
893 static void set_default(struct device_handler *handler,
894                 struct discover_boot_option *opt)
895 {
896         enum default_priority cur_prio, new_prio;
897
898         if (!handler->autoboot_enabled)
899                 return;
900
901         pb_debug("handler: new default option: %s\n", opt->option->id);
902
903         new_prio = default_option_priority(handler, opt);
904
905         /* Anything outside our range prevents a default boot */
906         if (new_prio >= DEFAULT_PRIORITY_DISABLED)
907                 return;
908
909         pb_debug("handler: calculated priority %d\n", new_prio);
910
911         /* Resolve any conflicts: if we have a new default option, it only
912          * replaces the current if it has a higher priority. */
913         if (handler->default_boot_option) {
914
915                 cur_prio = handler->default_boot_option_priority;
916
917                 if (new_prio < cur_prio) {
918                         pb_log("handler: new prio %d beats "
919                                         "old prio %d for %s\n",
920                                         new_prio, cur_prio,
921                                         handler->default_boot_option
922                                                 ->option->id);
923                         handler->default_boot_option = opt;
924                         handler->default_boot_option_priority = new_prio;
925                         /* extend the timeout a little, so the user sees some
926                          * indication of the change */
927                         handler->sec_to_boot += 2;
928                 }
929
930                 return;
931         }
932
933         if (handler->default_boot_option)
934                 handler->default_boot_option->option->is_autoboot_default = false;
935         opt->option->is_autoboot_default = true;
936
937         handler->sec_to_boot = config_get()->autoboot_timeout_sec;
938         handler->default_boot_option = opt;
939         handler->default_boot_option_priority = new_prio;
940
941         pb_log("handler: boot option %s set as default, timeout %u sec.\n",
942                opt->option->id, handler->sec_to_boot);
943
944         default_timeout(handler);
945 }
946
947 static char *autoboot_option_desc(void *ctx, const struct autoboot_option *opt)
948 {
949         const char *type, *val;
950
951         if (opt->boot_type == BOOT_DEVICE_TYPE) {
952                 type = _("device type");
953                 val = device_type_display_name(opt->type);
954         } else if (opt->boot_type == BOOT_DEVICE_UUID) {
955                 type = _("device UUID");
956                 val = opt->uuid;
957         } else {
958                 type = _("unknown specifier");
959                 val = NULL;
960         }
961
962         return talloc_asprintf(ctx, "%s = %s", type, val);
963 }
964
965 void device_handler_apply_temp_autoboot(struct device_handler *handler,
966                 struct autoboot_option *opt)
967 {
968         unsigned int i;
969         char *desc;
970
971         handler->temp_autoboot = talloc_steal(handler, opt);
972
973         desc = autoboot_option_desc(handler, opt);
974         device_handler_status_info(handler,
975                         _("Applying temporary autoboot override: %s"),
976                         desc);
977         talloc_free(desc);
978
979         if (!handler->autoboot_enabled)
980                 return;
981
982         if (!handler->default_boot_option)
983                 return;
984
985         if (autoboot_option_matches(opt, handler->default_boot_option->device))
986                 return;
987
988         /* cancel the default, and rescan available options */
989         device_handler_cancel_default(handler);
990
991         handler->autoboot_enabled = true;
992
993         for (i = 0; i < handler->n_devices; i++) {
994                 struct discover_device *dev = handler->devices[i];
995                 struct discover_boot_option *boot_opt;
996
997                 if (!autoboot_option_matches(opt, dev))
998                         continue;
999
1000                 list_for_each_entry(&dev->boot_options, boot_opt, list) {
1001                         if (boot_opt->option->is_default) {
1002                                 set_default(handler, boot_opt);
1003                                 break;
1004                         }
1005                 }
1006         }
1007 }
1008
1009 static bool resource_is_resolved(struct resource *res)
1010 {
1011         return !res || res->resolved;
1012 }
1013
1014 /* We only use this in an assert, which will disappear if we're compiling
1015  * with NDEBUG, so we need the 'used' attribute for these builds */
1016 static bool __attribute__((used)) boot_option_is_resolved(
1017                 struct discover_boot_option *opt)
1018 {
1019         return resource_is_resolved(opt->boot_image) &&
1020                 resource_is_resolved(opt->initrd) &&
1021                 resource_is_resolved(opt->dtb) &&
1022                 resource_is_resolved(opt->args_sig_file) &&
1023                 resource_is_resolved(opt->icon);
1024 }
1025
1026 static bool resource_resolve(struct resource *res, const char *name,
1027                 struct discover_boot_option *opt,
1028                 struct device_handler *handler)
1029 {
1030         struct parser *parser = opt->source;
1031
1032         if (resource_is_resolved(res))
1033                 return true;
1034
1035         pb_debug("Attempting to resolve resource %s->%s with parser %s\n",
1036                         opt->option->id, name, parser->name);
1037         parser->resolve_resource(handler, res);
1038
1039         return res->resolved;
1040 }
1041
1042 static bool boot_option_resolve(struct discover_boot_option *opt,
1043                 struct device_handler *handler)
1044 {
1045         return resource_resolve(opt->boot_image, "boot_image", opt, handler) &&
1046                 resource_resolve(opt->initrd, "initrd", opt, handler) &&
1047                 resource_resolve(opt->dtb, "dtb", opt, handler) &&
1048                 resource_resolve(opt->args_sig_file, "args_sig_file", opt,
1049                         handler) &&
1050                 resource_resolve(opt->icon, "icon", opt, handler);
1051 }
1052
1053 static void boot_option_finalise(struct device_handler *handler,
1054                 struct discover_boot_option *opt)
1055 {
1056         assert(boot_option_is_resolved(opt));
1057
1058         /* check that the parsers haven't set any of the final data */
1059         assert(!opt->option->boot_image_file);
1060         assert(!opt->option->initrd_file);
1061         assert(!opt->option->dtb_file);
1062         assert(!opt->option->icon_file);
1063         assert(!opt->option->device_id);
1064         assert(!opt->option->args_sig_file);
1065
1066         if (opt->boot_image)
1067                 opt->option->boot_image_file = opt->boot_image->url->full;
1068         if (opt->initrd)
1069                 opt->option->initrd_file = opt->initrd->url->full;
1070         if (opt->dtb)
1071                 opt->option->dtb_file = opt->dtb->url->full;
1072         if (opt->icon)
1073                 opt->option->icon_file = opt->icon->url->full;
1074         if (opt->args_sig_file)
1075                 opt->option->args_sig_file = opt->args_sig_file->url->full;
1076
1077         opt->option->device_id = opt->device->device->id;
1078
1079         if (opt->option->is_default)
1080                 set_default(handler, opt);
1081 }
1082
1083 static void notify_boot_option(struct device_handler *handler,
1084                 struct discover_boot_option *opt)
1085 {
1086         struct discover_device *dev = opt->device;
1087
1088         if (!dev->notified)
1089                 discover_server_notify_device_add(handler->server,
1090                                                   opt->device->device);
1091         dev->notified = true;
1092         discover_server_notify_boot_option_add(handler->server, opt->option);
1093 }
1094
1095 static void process_boot_option_queue(struct device_handler *handler)
1096 {
1097         struct discover_boot_option *opt, *tmp;
1098
1099         list_for_each_entry_safe(&handler->unresolved_boot_options,
1100                         opt, tmp, list) {
1101
1102                 pb_debug("queue: attempting resolution for %s\n",
1103                                 opt->option->id);
1104
1105                 if (!boot_option_resolve(opt, handler))
1106                         continue;
1107
1108                 pb_debug("\tresolved!\n");
1109
1110                 list_remove(&opt->list);
1111                 list_add_tail(&opt->device->boot_options, &opt->list);
1112                 talloc_steal(opt->device, opt);
1113                 boot_option_finalise(handler, opt);
1114                 notify_boot_option(handler, opt);
1115         }
1116 }
1117
1118 struct discover_context *device_handler_discover_context_create(
1119                 struct device_handler *handler,
1120                 struct discover_device *device)
1121 {
1122         struct discover_context *ctx;
1123
1124         ctx = talloc_zero(handler, struct discover_context);
1125         ctx->handler = handler;
1126         ctx->device = device;
1127         list_init(&ctx->boot_options);
1128
1129         return ctx;
1130 }
1131
1132 void device_handler_add_device(struct device_handler *handler,
1133                 struct discover_device *device)
1134 {
1135         handler->n_devices++;
1136         handler->devices = talloc_realloc(handler, handler->devices,
1137                                 struct discover_device *, handler->n_devices);
1138         handler->devices[handler->n_devices - 1] = device;
1139
1140         if (device->device->type == DEVICE_TYPE_NETWORK)
1141                 network_register_device(handler->network, device);
1142 }
1143
1144 void device_handler_add_ramdisk(struct device_handler *handler,
1145                 const char *path)
1146 {
1147         struct ramdisk_device *dev;
1148         unsigned int i;
1149
1150         if (!path)
1151                 return;
1152
1153         for (i = 0; i < handler->n_ramdisks; i++)
1154                 if (!strcmp(handler->ramdisks[i]->path, path))
1155                         return;
1156
1157         dev = talloc_zero(handler, struct ramdisk_device);
1158         if (!dev) {
1159                 pb_log("Failed to allocate memory to track %s\n", path);
1160                 return;
1161         }
1162
1163         dev->path = talloc_strdup(handler, path);
1164
1165         handler->ramdisks = talloc_realloc(handler, handler->ramdisks,
1166                                 struct ramdisk_device *,
1167                                 handler->n_ramdisks + 1);
1168         if (!handler->ramdisks) {
1169                 pb_log("Failed to reallocate memory"
1170                        "- ramdisk tracking inconsistent!\n");
1171                 return;
1172         }
1173
1174         handler->ramdisks[i] = dev;
1175         i = handler->n_ramdisks++;
1176 }
1177
1178 struct ramdisk_device *device_handler_get_ramdisk(
1179                 struct device_handler *handler)
1180 {
1181         unsigned int i;
1182         char *name;
1183         dev_t id;
1184
1185         /* Check if free ramdisk exists */
1186         for (i = 0; i < handler->n_ramdisks; i++)
1187                 if (!handler->ramdisks[i]->snapshot &&
1188                     !handler->ramdisks[i]->origin &&
1189                     !handler->ramdisks[i]->base)
1190                         return handler->ramdisks[i];
1191
1192         /* Otherwise create a new one */
1193         name = talloc_asprintf(handler, "/dev/ram%d",
1194                         handler->n_ramdisks);
1195         if (!name) {
1196                 pb_debug("Failed to allocate memory to name /dev/ram%d",
1197                         handler->n_ramdisks);
1198                 return NULL;
1199         }
1200
1201         id = makedev(1, handler->n_ramdisks);
1202         if (mknod(name, S_IFBLK, id)) {
1203                 if (errno == EEXIST) {
1204                         /* We haven't yet received updates for existing
1205                          * ramdisks - add and use this one */
1206                         pb_debug("Using untracked ramdisk %s\n", name);
1207                 } else {
1208                         pb_log("Failed to create new ramdisk %s: %s\n",
1209                                name, strerror(errno));
1210                         return NULL;
1211                 }
1212         }
1213         device_handler_add_ramdisk(handler, name);
1214         talloc_free(name);
1215
1216         return handler->ramdisks[i];
1217 }
1218
1219 void device_handler_release_ramdisk(struct discover_device *device)
1220 {
1221         struct ramdisk_device *ramdisk = device->ramdisk;
1222
1223         talloc_free(ramdisk->snapshot);
1224         talloc_free(ramdisk->origin);
1225         talloc_free(ramdisk->base);
1226
1227         ramdisk->snapshot = ramdisk->origin = ramdisk->base = NULL;
1228         ramdisk->sectors = 0;
1229
1230         device->ramdisk = NULL;
1231 }
1232
1233 /* Start discovery on a hotplugged device. The device will be in our devices
1234  * array, but has only just been initialised by the hotplug source.
1235  */
1236 int device_handler_discover(struct device_handler *handler,
1237                 struct discover_device *dev)
1238 {
1239         struct discover_context *ctx;
1240         int rc;
1241
1242         device_handler_status_dev_info(handler, dev,
1243                 /*
1244                  * TRANSLATORS: this string will be passed the type of the
1245                  * device (eg "disk" or "network"), which will be translated
1246                  * accordingly.
1247                  */
1248                 _("Processing new %s device"),
1249                 device_type_display_name(dev->device->type));
1250
1251         /* create our context */
1252         ctx = device_handler_discover_context_create(handler, dev);
1253
1254         rc = mount_device(dev);
1255         if (rc)
1256                 goto out;
1257
1258         /* add this device to our system info */
1259         system_info_register_blockdev(dev->device->id, dev->uuid,
1260                         dev->mount_path);
1261
1262         /* run the parsers. This will populate the ctx's boot_option list. */
1263         iterate_parsers(ctx);
1264
1265         /* add discovered stuff to the handler */
1266         device_handler_discover_context_commit(handler, ctx);
1267
1268         process_boot_option_queue(handler);
1269
1270         /* Check this device for pb-plugins */
1271         device_handler_plugin_scan_device(handler, dev);
1272 out:
1273         talloc_unlink(handler, ctx);
1274
1275         return 0;
1276 }
1277
1278 struct requery_data {
1279         struct device_handler   *handler;
1280         struct discover_device  *device;
1281 };
1282
1283 static int device_handler_requery_timeout_fn(void *data)
1284 {
1285         struct discover_boot_option *opt, *tmp;
1286         struct requery_data *rqd = data;
1287         struct device_handler *handler;
1288         struct discover_device *device;
1289         bool autoboot;
1290
1291         handler = rqd->handler;
1292         device = rqd->device;
1293
1294         talloc_free(rqd);
1295
1296         /* network_requery_device may re-add a timeout, so clear the device
1297          * waiter here, so we can potentially start a new one. */
1298         device->requery_waiter = NULL;
1299
1300         /* We keep the device around, but get rid of the parsed boot
1301          * options on that device. That involves delaring out the lists,
1302          * and potentially cancelling a default.
1303          */
1304         list_for_each_entry_safe(&handler->unresolved_boot_options,
1305                         opt, tmp, list) {
1306                 if (opt->device != device)
1307                         continue;
1308                 list_remove(&opt->list);
1309                 talloc_free(opt);
1310         }
1311
1312         /* Track whether autoboot was enabled, if we cancel a default option
1313          * it will be switched off.
1314          */
1315         autoboot = handler->autoboot_enabled;
1316
1317         list_for_each_entry_safe(&device->boot_options, opt, tmp, list) {
1318                 if (opt == handler->default_boot_option) {
1319                         pb_log("Default option %s cancelled since device is being requeried\n",
1320                                         opt->option->name);
1321                         device_handler_cancel_default(handler);
1322                 }
1323                 list_remove(&opt->list);
1324                 talloc_free(opt);
1325         }
1326
1327         handler->autoboot_enabled = autoboot;
1328
1329         discover_server_notify_device_remove(handler->server, device->device);
1330         device->notified = false;
1331
1332         network_requery_device(handler->network, device);
1333
1334         return 0;
1335 }
1336
1337 /* Schedule a requery in timeout (seconds).
1338  *
1339  * Special values of timeout:
1340  *   0: no requery
1341  *  -1: use default
1342  */
1343 void device_handler_start_requery_timeout( struct device_handler *handler,
1344                 struct discover_device *dev, int timeout)
1345 {
1346         struct requery_data *rqd;
1347
1348         if (dev->requery_waiter)
1349                 return;
1350
1351         if (timeout == -1)
1352                 timeout = default_rescan_timeout;
1353         else if (timeout == 0)
1354                 return;
1355
1356         rqd = talloc(dev, struct requery_data);
1357         rqd->handler = handler;
1358         rqd->device = dev;
1359
1360         pb_debug("starting requery timeout for device %s, in %d sec\n",
1361                         dev->device->id, timeout);
1362
1363         dev->requery_waiter = waiter_register_timeout(handler->waitset,
1364                         timeout * 1000, device_handler_requery_timeout_fn, rqd);
1365 }
1366
1367 static int event_requery_timeout(struct event *event)
1368 {
1369         int timeout = -1;
1370         unsigned long x;
1371         const char *str;
1372         char *endp;
1373
1374         if (!event)
1375                 return timeout;
1376
1377         str = event_get_param(event, "reboottime");
1378         if (!str)
1379                 return timeout;
1380
1381         x = strtoul(str, &endp, 0);
1382         if (endp != str)
1383                 timeout = x;
1384
1385         return timeout;
1386 }
1387
1388
1389 /* Incoming dhcp event */
1390 int device_handler_dhcp(struct device_handler *handler,
1391                 struct discover_device *dev, struct event *event)
1392 {
1393         struct discover_context *ctx;
1394         const char *ip;
1395
1396         if (event_get_param(event, "ipv6"))
1397                 ip = event_get_param(event, "ipv6");
1398         else
1399                 ip = event_get_param(event, "ip");
1400
1401         device_handler_status_dev_info(handler, dev,
1402                         _("Processing DHCP lease response (ip: %s)"), ip);
1403
1404         pending_network_jobs_start();
1405
1406         /* create our context */
1407         ctx = device_handler_discover_context_create(handler, dev);
1408         talloc_steal(ctx, event);
1409         ctx->event = event;
1410
1411         device_handler_start_requery_timeout(handler, dev,
1412                         event_requery_timeout(event));
1413
1414         iterate_parsers(ctx);
1415
1416         device_handler_discover_context_commit(handler, ctx);
1417
1418         talloc_unlink(handler, ctx);
1419
1420         return 0;
1421 }
1422
1423 struct discover_boot_option *device_handler_find_option_by_name(
1424                 struct device_handler *handler, const char *device,
1425                 const char *name)
1426 {
1427         size_t len = strlen(name);
1428         unsigned int i;
1429
1430         for (i = 0; i < handler->n_devices; i++) {
1431                 struct discover_device *dev = handler->devices[i];
1432                 struct discover_boot_option *opt;
1433
1434                 list_for_each_entry(&dev->boot_options, opt, list)
1435                         /* Match exactly, partial matches can be quite common */
1436                         if (strlen(opt->option->name) == len &&
1437                                         !strcmp(opt->option->name, name))
1438                                 if (!dev || !strcmp(opt->option->device_id, device))
1439                                         return opt;
1440         }
1441
1442         return NULL;
1443 }
1444
1445 static struct discover_boot_option *find_boot_option_by_id(
1446                 struct device_handler *handler, const char *id)
1447 {
1448         unsigned int i;
1449
1450         for (i = 0; i < handler->n_devices; i++) {
1451                 struct discover_device *dev = handler->devices[i];
1452                 struct discover_boot_option *opt;
1453
1454                 list_for_each_entry(&dev->boot_options, opt, list)
1455                         if (!strcmp(opt->option->id, id))
1456                                 return opt;
1457         }
1458
1459         return NULL;
1460 }
1461
1462 void device_handler_boot(struct device_handler *handler,
1463                 bool change_default, struct boot_command *cmd)
1464 {
1465         struct discover_boot_option *opt = NULL;
1466
1467         if (cmd->option_id && strlen(cmd->option_id))
1468                 opt = find_boot_option_by_id(handler, cmd->option_id);
1469
1470         /* Don't allow a normal client to change the default */
1471         if (!change_default && handler->last_boot_option &&
1472                         opt != handler->last_boot_option) {
1473                 pb_log("Non-root user tried to change boot option\n");
1474                 device_handler_status_err(handler,
1475                                 "Must be root to change default boot option\n");
1476                 return;
1477         }
1478
1479         if (handler->pending_boot)
1480                 boot_cancel(handler->pending_boot);
1481
1482         platform_pre_boot();
1483
1484         handler->pending_boot = boot(handler, opt, cmd, handler->dry_run,
1485                         device_handler_boot_status_cb, handler);
1486         handler->pending_boot_is_default = false;
1487 }
1488
1489 void device_handler_cancel_default(struct device_handler *handler)
1490 {
1491         if (handler->timeout_waiter)
1492                 waiter_remove(handler->timeout_waiter);
1493
1494         handler->timeout_waiter = NULL;
1495         handler->autoboot_enabled = false;
1496
1497         /* we only send status if we had a default boot option queued */
1498         if (!handler->default_boot_option)
1499                 return;
1500
1501         pb_log("Cancelling default boot option\n");
1502
1503         if (handler->pending_boot && handler->pending_boot_is_default) {
1504                 boot_cancel(handler->pending_boot);
1505                 handler->pending_boot = NULL;
1506                 handler->pending_boot_is_default = false;
1507         }
1508
1509         handler->default_boot_option = NULL;
1510
1511         device_handler_status_info(handler, _("Default boot cancelled"));
1512 }
1513
1514 void device_handler_update_config(struct device_handler *handler,
1515                 struct config *config)
1516 {
1517         int rc;
1518
1519         rc = config_set(config);
1520         if (rc) {
1521                 device_handler_status_err(handler,
1522                                 "Failed to update configuration!");
1523                 return;
1524         }
1525
1526         discover_server_notify_config(handler->server, config);
1527         device_handler_update_lang(config->lang);
1528         device_handler_reinit(handler);
1529 }
1530
1531 static char *device_from_addr(void *ctx, struct pb_url *url)
1532 {
1533         char *ipaddr, *buf, *tok, *dev = NULL;
1534         bool ipv6_route;
1535         const char *delim = " ";
1536         struct sockaddr_in *ipv4;
1537         struct sockaddr_in6 *ipv6;
1538         struct addrinfo *res;
1539         struct process *p;
1540         int rc;
1541
1542         /* Confirm url->host is either a valid hostname, or a
1543          * valid IPv4 or IPv6 address */
1544         rc = getaddrinfo(url->host, NULL, NULL, &res);
1545         if (rc) {
1546                 pb_debug("%s: Invalid URL\n",__func__);
1547                 return NULL;
1548         }
1549
1550         switch (res->ai_family) {
1551         case AF_INET:   /* ipv4 */
1552                 ipaddr = talloc_array(ctx,char,INET_ADDRSTRLEN);
1553                 ipv4 = (struct sockaddr_in *) res->ai_addr;
1554                 inet_ntop(AF_INET, &(ipv4->sin_addr), ipaddr, INET_ADDRSTRLEN);
1555                 ipv6_route = false;
1556                 break;
1557         case AF_INET6:  /* ipv6 */
1558                 ipaddr = talloc_array(ctx,char,INET6_ADDRSTRLEN);
1559                 ipv6 = (struct sockaddr_in6 *) res->ai_addr;
1560                 inet_ntop(AF_INET6, &(ipv6->sin6_addr), ipaddr, INET6_ADDRSTRLEN);
1561                 ipv6_route = true;
1562                 break;
1563         default:        /* error */
1564                 freeaddrinfo(res);
1565                 return NULL;
1566         }
1567         freeaddrinfo(res);
1568
1569         const char *argv[] = {
1570                 pb_system_apps.ip,
1571                 ipv6_route ? "-6" : "-4",
1572                 "route", "show", "to", "match",
1573                 ipaddr,
1574                 NULL
1575         };
1576
1577         p = process_create(ctx);
1578
1579         p->path = pb_system_apps.ip;
1580         p->argv = argv;
1581         p->keep_stdout = true;
1582
1583         rc = process_run_sync(p);
1584
1585         if (rc || p->exit_status) {
1586                 /* ip has complained for some reason; most likely
1587                  * there is no route to the host - bail out */
1588                 pb_debug("%s: `ip` returns non-zero exit status\n", __func__);
1589                 pb_debug("ip buf: %s\n", p->stdout_buf);
1590                 process_release(p);
1591                 return NULL;
1592         }
1593
1594         buf = p->stdout_buf;
1595         /* If a route is found, ip-route output will be of the form
1596          * "... dev DEVNAME ... " */
1597         tok = strtok(buf, delim);
1598         while (tok) {
1599                 if (!strcmp(tok, "dev")) {
1600                         tok = strtok(NULL, delim);
1601                         dev = talloc_strdup(ctx, tok);
1602                         break;
1603                 }
1604                 tok = strtok(NULL, delim);
1605         }
1606
1607         process_release(p);
1608         if (dev)
1609                 pb_debug("%s: Found interface '%s'\n", __func__,dev);
1610         return dev;
1611 }
1612
1613 static void process_url_cb(struct load_url_result *result, void *data)
1614 {
1615         struct device_handler *handler;
1616         struct discover_context *ctx;
1617         struct discover_device *dev;
1618         struct event *event = data;
1619         const char *mac;
1620
1621         if (result->status != LOAD_OK) {
1622                 pb_log_fn("Load failed for %s\n", result->url->full);
1623                 return;
1624         }
1625
1626         if (!event)
1627                 return;
1628
1629         handler = talloc_parent(event);
1630         if (!handler)
1631                 return;
1632
1633         event->device = device_from_addr(event, result->url);
1634         if (!event->device) {
1635                 pb_log("Downloaded a file but can't find its interface - pretending it was local\n");
1636                 event->device = talloc_asprintf(event, "local");
1637         }
1638
1639         mac = event_get_param(event, "mac");
1640         char *url = talloc_asprintf(event, "file://%s", result->local);
1641         event_set_param(event, "pxeconffile-local", url);
1642
1643         dev = discover_device_create(handler, mac, event->device);
1644         ctx = device_handler_discover_context_create(handler, dev);
1645         talloc_steal(ctx, event);
1646         ctx->event = event;
1647
1648         iterate_parsers(ctx);
1649
1650         device_handler_discover_context_commit(handler, ctx);
1651
1652         talloc_unlink(handler, ctx);
1653 }
1654
1655 void device_handler_process_url(struct device_handler *handler,
1656                 const char *url, const char *mac, const char *ip)
1657 {
1658         struct discover_context *ctx;
1659         struct discover_device *dev;
1660         bool allow_async = false;
1661         struct pb_url *pb_url;
1662         struct event *event;
1663
1664         event = talloc_zero(handler, struct event);
1665         event->type = EVENT_TYPE_USER;
1666         event->action = EVENT_ACTION_URL;
1667
1668         pb_url = pb_url_parse(event, url);
1669         if (!pb_url || (pb_url->scheme != pb_url_file && !pb_url->host)) {
1670                 device_handler_status_err(handler, _("Invalid config URL!"));
1671                 talloc_free(event);
1672                 return;
1673         }
1674
1675         if (url[strlen(url) - 1] == '/') {
1676                 event_set_param(event, "pxepathprefix", url);
1677                 event_set_param(event, "mac", mac);
1678                 event_set_param(event, "ip", ip);
1679                 event->device = device_from_addr(event, pb_url);
1680                 if (!event->device) {
1681                         device_handler_status_err(handler,
1682                                         _("Unable to route to host %s"),
1683                                         pb_url->host);
1684                         talloc_free(event);
1685                         return;
1686                 }
1687         } else {
1688                 event_set_param(event, "pxeconffile", url);
1689                 allow_async = true;
1690         }
1691
1692         if (pb_url->scheme == pb_url_file)
1693                 event->device = talloc_asprintf(event, "local");
1694         else if (allow_async) {
1695                 /* If file is remote load asynchronously before passing to
1696                  * parser. This allows us to wait for network to be available */
1697                 if (!load_url_async(handler, pb_url, process_url_cb, event,
1698                                         NULL, handler)) {
1699                         pb_log("Failed to load url %s\n", pb_url->full);
1700                         device_handler_status_err(handler, _("Failed to load URL!"));
1701                         talloc_free(event);
1702                 }
1703                 return;
1704         }
1705
1706         /* If path is local we can parse straight away */
1707
1708         dev = discover_device_create(handler, mac, event->device);
1709         if (pb_url->scheme == pb_url_file)
1710                 dev->device->type = DEVICE_TYPE_ANY;
1711         ctx = device_handler_discover_context_create(handler, dev);
1712         talloc_steal(ctx, event);
1713         ctx->event = event;
1714
1715         iterate_parsers(ctx);
1716
1717         device_handler_discover_context_commit(handler, ctx);
1718
1719         talloc_unlink(handler, ctx);
1720 }
1721
1722 static void plugin_install_cb(struct process *process)
1723 {
1724         struct device_handler *handler = process->data;
1725
1726         if (!handler) {
1727                 pb_log_fn("Missing data!\n");
1728                 return;
1729         }
1730
1731         handler->plugin_installing = false;
1732         if (process->exit_status) {
1733                 device_handler_status_err(handler, "Plugin failed to install!");
1734                 pb_log("Failed to install plugin:\n%s\n", process->stdout_buf);
1735         }
1736 }
1737
1738 void device_handler_install_plugin(struct device_handler *handler,
1739                 const char *plugin_file)
1740 {
1741         struct process *p;
1742         int result;
1743
1744         if (handler->plugin_installing) {
1745                 pb_log("Plugin install cancelled - install already running");
1746                 return;
1747         }
1748
1749         p = process_create(handler);
1750         if (!p) {
1751                 pb_log("install_plugin: Failed to create process\n");
1752                 return;
1753         }
1754
1755         const char *argv[] = {
1756                 pb_system_apps.pb_plugin,
1757                 "install",
1758                 "auto",
1759                 plugin_file,
1760                 NULL
1761         };
1762
1763         p->path = pb_system_apps.pb_plugin;
1764         p->argv = argv;
1765         p->exit_cb = plugin_install_cb;
1766         p->data = handler;
1767         p->keep_stdout = true;
1768
1769         result = process_run_async(p);
1770
1771         if (result)
1772                 device_handler_status_err(handler, "Could not install plugin");
1773         else
1774                 handler->plugin_installing = true;
1775 }
1776
1777 #ifndef PETITBOOT_TEST
1778
1779 /**
1780  * context_commit - Commit a temporary discovery context to the handler,
1781  * and notify the clients about any new options / devices
1782  */
1783 void device_handler_discover_context_commit(struct device_handler *handler,
1784                 struct discover_context *ctx)
1785 {
1786         struct discover_device *dev = ctx->device;
1787         struct discover_boot_option *opt, *tmp;
1788
1789         if (!device_lookup_by_uuid(handler, dev->uuid))
1790                 device_handler_add_device(handler, dev);
1791
1792         /* move boot options from the context to the device */
1793         list_for_each_entry_safe(&ctx->boot_options, opt, tmp, list) {
1794                 list_remove(&opt->list);
1795
1796                 /* All boot options need at least a kernel image */
1797                 if (!opt->boot_image || !opt->boot_image->url) {
1798                         pb_log("boot option %s is missing boot image, ignoring\n",
1799                                 opt->option->id);
1800                         talloc_free(opt);
1801                         continue;
1802                 }
1803
1804                 if (boot_option_resolve(opt, handler)) {
1805                         pb_log("boot option %s is resolved, "
1806                                         "sending to clients\n",
1807                                         opt->option->id);
1808                         list_add_tail(&dev->boot_options, &opt->list);
1809                         talloc_steal(dev, opt);
1810                         boot_option_finalise(handler, opt);
1811                         notify_boot_option(handler, opt);
1812                 } else {
1813                         if (!opt->source->resolve_resource) {
1814                                 pb_log("parser %s gave us an unresolved "
1815                                         "resource (%s), but no way to "
1816                                         "resolve it\n",
1817                                         opt->source->name, opt->option->id);
1818                                 talloc_free(opt);
1819                         } else {
1820                                 pb_log("boot option %s is unresolved, "
1821                                                 "adding to queue\n",
1822                                                 opt->option->id);
1823                                 list_add(&handler->unresolved_boot_options,
1824                                                 &opt->list);
1825                                 talloc_steal(handler, opt);
1826                         }
1827                 }
1828         }
1829 }
1830
1831 void device_handler_add_plugin_option(struct device_handler *handler,
1832                 struct plugin_option *opt)
1833 {
1834         struct plugin_option *tmp;
1835         unsigned int i;
1836
1837         for (i = 0; i < handler->n_plugins; i++) {
1838                 tmp = handler->plugins[i];
1839                 /* If both id and version match, ignore */
1840                 if (strncmp(opt->id, tmp->id, strlen(opt->id)) == 0 &&
1841                                 strcmp(opt->version, tmp->version) == 0) {
1842                         pb_log("discover: Plugin '%s' already exists, ignoring\n",
1843                                         opt->id);
1844                         return;
1845                 }
1846         }
1847
1848         handler->plugins = talloc_realloc(handler, handler->plugins,
1849                         struct plugin_option *, handler->n_plugins + 1);
1850         if (!handler->plugins) {
1851                 pb_log("Failed to allocate memory for new plugin\n");
1852                 handler->n_plugins = 0;
1853                 return;
1854         }
1855
1856         handler->plugins[handler->n_plugins++] = opt;
1857         discover_server_notify_plugin_option_add(handler->server, opt);
1858 }
1859
1860 static void device_handler_update_lang(const char *lang)
1861 {
1862         const char *cur_lang;
1863
1864         if (!lang)
1865                 return;
1866
1867         cur_lang = setlocale(LC_ALL, NULL);
1868         if (cur_lang && !strcmp(cur_lang, lang))
1869                 return;
1870
1871         setlocale(LC_ALL, lang);
1872 }
1873
1874 static int device_handler_init_sources(struct device_handler *handler)
1875 {
1876         /* init our device sources: udev, network and user events */
1877         handler->user_event = user_event_init(handler, handler->waitset);
1878         if (!handler->user_event)
1879                 return -1;
1880
1881         handler->network = network_init(handler, handler->waitset,
1882                         handler->dry_run);
1883         if (!handler->network)
1884                 return -1;
1885
1886         handler->udev = udev_init(handler, handler->waitset);
1887         if (!handler->udev)
1888                 return -1;
1889
1890         return 0;
1891 }
1892
1893 static void device_handler_reinit_sources(struct device_handler *handler)
1894 {
1895         /* if we haven't initialised sources previously (becuase we started in
1896          * safe mode), then init once here. */
1897         if (!(handler->udev || handler->network || handler->user_event)) {
1898                 device_handler_init_sources(handler);
1899                 return;
1900         }
1901
1902         system_info_reinit();
1903
1904         network_shutdown(handler->network);
1905         handler->network = network_init(handler, handler->waitset,
1906                         handler->dry_run);
1907
1908         udev_reinit(handler->udev);
1909 }
1910
1911 static inline const char *get_device_path(struct discover_device *dev)
1912 {
1913         return dev->ramdisk ? dev->ramdisk->snapshot : dev->device_path;
1914 }
1915
1916 static char *check_subvols(struct discover_device *dev)
1917 {
1918         const char *fstype = discover_device_get_param(dev, "ID_FS_TYPE");
1919         struct stat sb;
1920         char *path;
1921         int rc;
1922
1923         if (strncmp(fstype, "btrfs", strlen("btrfs")))
1924                 return dev->mount_path;
1925
1926         /* On btrfs a device's root may be under a subvolume path */
1927         path = join_paths(dev, dev->mount_path, "@");
1928         rc = stat(path, &sb);
1929         if (!rc && S_ISDIR(sb.st_mode)) {
1930                 pb_debug("Using '%s' for btrfs root path\n", path);
1931                 return path;
1932         }
1933
1934         talloc_free(path);
1935         return dev->mount_path;
1936 }
1937
1938 static bool check_existing_mount(struct discover_device *dev)
1939 {
1940         struct stat devstat, mntstat;
1941         const char *device_path;
1942         struct mntent *mnt;
1943         FILE *fp;
1944         int rc;
1945
1946         device_path = get_device_path(dev);
1947
1948         rc = stat(device_path, &devstat);
1949         if (rc) {
1950                 pb_debug("%s: stat failed: %s\n", __func__, strerror(errno));
1951                 return false;
1952         }
1953
1954         if (!S_ISBLK(devstat.st_mode)) {
1955                 pb_debug("%s: %s isn't a block device?\n", __func__,
1956                                 dev->device_path);
1957                 return false;
1958         }
1959
1960         fp = fopen("/proc/self/mounts", "r");
1961
1962         for (;;) {
1963                 mnt = getmntent(fp);
1964                 if (!mnt)
1965                         break;
1966
1967                 if (!mnt->mnt_fsname || mnt->mnt_fsname[0] != '/')
1968                         continue;
1969
1970                 rc = stat(mnt->mnt_fsname, &mntstat);
1971                 if (rc)
1972                         continue;
1973
1974                 if (!S_ISBLK(mntstat.st_mode))
1975                         continue;
1976
1977                 if (mntstat.st_rdev == devstat.st_rdev) {
1978                         dev->mount_path = talloc_strdup(dev, mnt->mnt_dir);
1979                         dev->root_path = check_subvols(dev);
1980                         dev->mounted_rw = !!hasmntopt(mnt, "rw");
1981                         dev->mounted = true;
1982                         dev->unmount = false;
1983
1984                         pb_debug("%s: %s is already mounted (r%c) at %s\n",
1985                                         __func__, dev->device_path,
1986                                         dev->mounted_rw ? 'w' : 'o',
1987                                         mnt->mnt_dir);
1988                         break;
1989                 }
1990         }
1991
1992         fclose(fp);
1993
1994         return mnt != NULL;
1995 }
1996
1997 /*
1998  * Attempt to mount a filesystem safely, while handling certain filesytem-
1999  * specific options
2000  */
2001 static int try_mount(const char *device_path, const char *mount_path,
2002                              const char *fstype, unsigned long flags,
2003                              bool have_snapshot)
2004 {
2005         const char *fs, *safe_opts;
2006         int rc;
2007
2008         /* Mount ext3 as ext4 instead so 'norecovery' can be used */
2009         if (strncmp(fstype, "ext3", strlen("ext3")) == 0) {
2010                 pb_debug("Mounting ext3 filesystem as ext4\n");
2011                 fs = "ext4";
2012         } else
2013                 fs = fstype;
2014
2015         if (strncmp(fs, "xfs", strlen("xfs")) == 0 ||
2016             strncmp(fs, "ext4", strlen("ext4")) == 0)
2017                 safe_opts = "norecovery";
2018         else
2019                 safe_opts = NULL;
2020
2021         errno = 0;
2022         /* If no snapshot is available don't attempt recovery */
2023         if (!have_snapshot)
2024                 return mount(device_path, mount_path, fs, flags, safe_opts);
2025
2026         rc = mount(device_path, mount_path, fs, flags, NULL);
2027
2028         if (!rc)
2029                 return rc;
2030
2031         /* Mounting failed; some filesystems will fail to mount if a recovery
2032          * journal exists (eg. cross-endian XFS), so try again with norecovery
2033          * where that option is available.
2034          * If mounting read-write just return the error as norecovery is not a
2035          * valid option */
2036         if ((flags & MS_RDONLY) != MS_RDONLY || !safe_opts)
2037                 return rc;
2038
2039         errno = 0;
2040         return mount(device_path, mount_path, fs, flags, safe_opts);
2041 }
2042
2043 static int mount_device(struct discover_device *dev)
2044 {
2045         const char *fstype, *device_path;
2046         int rc;
2047
2048         if (!dev->device_path)
2049                 return -1;
2050
2051         if (dev->mounted)
2052                 return 0;
2053
2054         if (check_existing_mount(dev))
2055                 return 0;
2056
2057         fstype = discover_device_get_param(dev, "ID_FS_TYPE");
2058         if (!fstype)
2059                 return 0;
2060
2061         dev->mount_path = join_paths(dev, mount_base(),
2062                                         dev->device_path);
2063
2064         if (pb_mkdir_recursive(dev->mount_path)) {
2065                 pb_log("couldn't create mount directory %s: %s\n",
2066                                 dev->mount_path, strerror(errno));
2067                 goto err_free;
2068         }
2069
2070         device_path = get_device_path(dev);
2071
2072         pb_log("mounting device %s read-only\n", dev->device_path);
2073         rc = try_mount(device_path, dev->mount_path, fstype,
2074                        MS_RDONLY | MS_SILENT, dev->ramdisk);
2075
2076         /* If mount fails clean up any snapshot and try again */
2077         if (rc && dev->ramdisk) {
2078                 pb_log("couldn't mount snapshot for %s: mount failed: %s\n",
2079                                 device_path, strerror(errno));
2080                 pb_log("falling back to actual device\n");
2081
2082                 devmapper_destroy_snapshot(dev);
2083
2084                 device_path = get_device_path(dev);
2085                 pb_log("mounting device %s read-only\n", dev->device_path);
2086                 rc = try_mount(device_path, dev->mount_path, fstype,
2087                                MS_RDONLY | MS_SILENT, dev->ramdisk);
2088         }
2089
2090         if (!rc) {
2091                 dev->mounted = true;
2092                 dev->mounted_rw = false;
2093                 dev->unmount = true;
2094                 dev->root_path = check_subvols(dev);
2095                 return 0;
2096         }
2097
2098         pb_log("couldn't mount device %s: mount failed: %s\n",
2099                         device_path, strerror(errno));
2100
2101         pb_rmdir_recursive(mount_base(), dev->mount_path);
2102 err_free:
2103         talloc_free(dev->mount_path);
2104         dev->mount_path = NULL;
2105         return -1;
2106 }
2107
2108 static int umount_device(struct discover_device *dev)
2109 {
2110         const char *device_path;
2111         int rc;
2112
2113         if (!dev->mounted || !dev->unmount)
2114                 return 0;
2115
2116         device_path = get_device_path(dev);
2117
2118         pb_log("unmounting device %s\n", device_path);
2119         rc = umount(dev->mount_path);
2120         if (rc)
2121                 return -1;
2122
2123         dev->mounted = false;
2124         devmapper_destroy_snapshot(dev);
2125
2126         pb_rmdir_recursive(mount_base(), dev->mount_path);
2127
2128         talloc_free(dev->mount_path);
2129         dev->mount_path = NULL;
2130         dev->root_path = NULL;
2131
2132         return 0;
2133 }
2134
2135 int device_request_write(struct discover_device *dev, bool *release)
2136 {
2137         const char *fstype, *device_path;
2138         const struct config *config;
2139         int rc;
2140
2141         *release = false;
2142
2143         config = config_get();
2144         if (!config->allow_writes)
2145                 return -1;
2146
2147         if (!dev->mounted)
2148                 return -1;
2149
2150         if (dev->mounted_rw)
2151                 return 0;
2152
2153         fstype = discover_device_get_param(dev, "ID_FS_TYPE");
2154
2155         device_path = get_device_path(dev);
2156
2157         pb_log("remounting device %s read-write\n", device_path);
2158
2159         rc = umount(dev->mount_path);
2160         if (rc) {
2161                 pb_log("Failed to unmount %s: %s\n",
2162                        dev->mount_path, strerror(errno));
2163                 return -1;
2164         }
2165
2166         rc = try_mount(device_path, dev->mount_path, fstype,
2167                        MS_SILENT, dev->ramdisk);
2168         if (rc)
2169                 goto mount_ro;
2170
2171         dev->mounted_rw = true;
2172         *release = true;
2173         return 0;
2174
2175 mount_ro:
2176         pb_log("Unable to remount device %s read-write: %s\n",
2177                device_path, strerror(errno));
2178         rc = try_mount(device_path, dev->mount_path, fstype,
2179                        MS_RDONLY | MS_SILENT, dev->ramdisk);
2180         if (rc)
2181                 pb_log("Unable to recover mount for %s: %s\n",
2182                        device_path, strerror(errno));
2183         return -1;
2184 }
2185
2186 void device_release_write(struct discover_device *dev, bool release)
2187 {
2188         const char *fstype, *device_path;
2189
2190         if (!release)
2191                 return;
2192
2193         device_path = get_device_path(dev);
2194
2195         fstype = discover_device_get_param(dev, "ID_FS_TYPE");
2196
2197         pb_log("remounting device %s read-only\n", device_path);
2198
2199         if (umount(dev->mount_path)) {
2200                 pb_log("Failed to unmount %s\n", dev->mount_path);
2201                 return;
2202         }
2203         dev->mounted_rw = dev->mounted = false;
2204
2205         if (dev->ramdisk) {
2206                 devmapper_merge_snapshot(dev);
2207                 /* device_path becomes stale after merge */
2208                 device_path = get_device_path(dev);
2209         }
2210
2211         if (try_mount(device_path, dev->mount_path, fstype,
2212                        MS_RDONLY | MS_SILENT, dev->ramdisk))
2213                 pb_log("Failed to remount %s read-only: %s\n",
2214                        device_path, strerror(errno));
2215         else
2216                 dev->mounted = true;
2217 }
2218
2219 void device_sync_snapshots(struct device_handler *handler, const char *device)
2220 {
2221         struct discover_device *dev = NULL;
2222         unsigned int i;
2223
2224         if (device) {
2225                 /* Find matching device and sync */
2226                 dev = device_lookup_by_name(handler, device);
2227                 if (!dev) {
2228                         pb_log("%s: device name '%s' unrecognised\n",
2229                                 __func__, device);
2230                         return;
2231                 }
2232                 if (dev->ramdisk)
2233                         device_release_write(dev, true);
2234                 else
2235                         pb_log("%s has no snapshot to merge, skipping\n",
2236                                 dev->device->id);
2237                 return;
2238         }
2239
2240         /* Otherwise sync all relevant devices */
2241         for (i = 0; i < handler->n_devices; i++) {
2242                 dev = handler->devices[i];
2243                 if (dev->device->type != DEVICE_TYPE_DISK &&
2244                         dev->device->type != DEVICE_TYPE_USB)
2245                         continue;
2246                 if (dev->ramdisk)
2247                         device_release_write(dev, true);
2248                 else
2249                         pb_log("%s has no snapshot to merge, skipping\n",
2250                                 dev->device->id);
2251         }
2252 }
2253
2254 #else
2255
2256 void device_handler_discover_context_commit(
2257                 struct device_handler *handler __attribute__((unused)),
2258                 struct discover_context *ctx __attribute__((unused)))
2259 {
2260         pb_log_fn("stubbed out for test cases\n");
2261 }
2262
2263 static void device_handler_update_lang(const char *lang __attribute__((unused)))
2264 {
2265 }
2266
2267 static int device_handler_init_sources(
2268                 struct device_handler *handler __attribute__((unused)))
2269 {
2270         return 0;
2271 }
2272
2273 static void device_handler_reinit_sources(
2274                 struct device_handler *handler __attribute__((unused)))
2275 {
2276 }
2277
2278 static int umount_device(struct discover_device *dev __attribute__((unused)))
2279 {
2280         return 0;
2281 }
2282
2283 static int __attribute__((unused)) mount_device(
2284                 struct discover_device *dev __attribute__((unused)))
2285 {
2286         return 0;
2287 }
2288
2289 int device_request_write(struct discover_device *dev __attribute__((unused)),
2290                 bool *release)
2291 {
2292         *release = true;
2293         return 0;
2294 }
2295
2296 void device_release_write(struct discover_device *dev __attribute__((unused)),
2297         bool release __attribute__((unused)))
2298 {
2299 }
2300
2301 void device_sync_snapshots(
2302                 struct device_handler *handler __attribute__((unused)),
2303                 const char *device __attribute__((unused)))
2304 {
2305 }
2306
2307 #endif