+ /* strip filename from the bootfile path, leaving only a
+ * directory */
+ p = strrchr(basedir, '/');
+ if (!p)
+ p = basedir;
+ *p = '\0';
+
+ if (strlen(basedir))
+ url_str = talloc_asprintf_append(url_str, "%s/",
+ basedir);
+
+ talloc_free(basedir);
+ }
+
+ /* finally, append conffile */
+ if (conffile)
+ url_str = talloc_asprintf_append(url_str, "%s", conffile);
+
+ url = pb_url_parse(ctx, url_str);
+
+ talloc_free(url_str);
+
+ return url;
+}
+
+char **user_event_parse_conf_filenames(
+ struct discover_context *ctx, struct event *event)
+{
+ char *mac_addr, *ip_hex;
+ const char *mac, *ip;
+ char **filenames;
+ int index, len;
+
+ mac = event_get_param(event, "mac");
+ if (mac)
+ mac_addr = parse_mac_addr(ctx, mac);
+ else
+ mac_addr = NULL;
+
+ ip = event_get_param(event, "ip");
+ if (ip) {
+ ip_hex = parse_ip_addr(ctx, ip);
+ len = strlen(ip_hex);
+ } else {
+ ip_hex = NULL;
+ len = 0;
+ }
+
+ if (!mac_addr && !ip_hex) {
+ pb_log("%s: neither mac nor ip parameter found\n", __func__);
+ return NULL;
+ }
+
+ /* Filenames as fallback IP's + mac + default */
+ filenames = talloc_array(ctx, char *, len + 3);
+
+ index = 0;
+ if (mac_addr)
+ filenames[index++] = talloc_strdup(filenames, mac_addr);
+
+ while (len) {
+ filenames[index++] = talloc_strdup(filenames, ip_hex);
+ ip_hex[--len] = '\0';
+ }
+
+ filenames[index++] = talloc_strdup(filenames, "default");
+ filenames[index++] = NULL;
+
+ if (mac_addr)
+ talloc_free(mac_addr);
+
+ if (ip_hex)
+ talloc_free(ip_hex);
+
+ return filenames;
+}
+
+static int user_event_dhcp(struct user_event *uev, struct event *event)
+{
+ struct device_handler *handler = uev->handler;
+ struct discover_device *dev;
+
+ uint8_t hwaddr[MAC_ADDR_SIZE];
+
+ sscanf(event_get_param(event, "mac"),
+ "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX",
+ hwaddr, hwaddr + 1, hwaddr + 2,
+ hwaddr + 3, hwaddr + 4, hwaddr + 5);
+
+ system_info_set_interface_address(sizeof(hwaddr), hwaddr,
+ event_get_param(event, "ip"));
+
+ dev = discover_device_create(handler, event_get_param(event, "mac"),
+ event->device);
+
+ device_handler_dhcp(handler, dev, event);
+
+ return 0;
+}
+
+static int user_event_add(struct user_event *uev, struct event *event)
+{
+ struct device_handler *handler = uev->handler;
+ struct discover_context *ctx;
+ struct discover_device *dev;
+
+ /* In case this is a network interface, try to refer to it by UUID */
+ dev = discover_device_create(handler, event_get_param(event, "mac"),
+ event->device);
+ dev->device->id = talloc_strdup(dev, event->device);
+ ctx = device_handler_discover_context_create(handler, dev);
+
+ parse_user_event(ctx, event);
+
+ device_handler_discover_context_commit(handler, ctx);
+
+ talloc_free(ctx);
+
+ return 0;
+}
+
+static int user_event_remove(struct user_event *uev, struct event *event)
+{
+ struct device_handler *handler = uev->handler;
+ struct discover_device *dev;
+ const char *mac = event_get_param(event, "mac");
+
+ if (mac)
+ dev = device_lookup_by_uuid(handler, event_get_param(event, "mac"));
+ else
+ dev = device_lookup_by_id(handler, event->device);
+
+ if (!dev)
+ return 0;
+
+ device_handler_remove(handler, dev);
+
+ return 0;
+}
+
+static int user_event_url(struct user_event *uev, struct event *event)
+{
+ struct device_handler *handler = uev->handler;
+ const char *url;
+
+ url = event_get_param(event, "url");
+ if (url)
+ device_handler_process_url(handler, url, NULL, NULL);
+
+ return 0;
+}
+
+static int user_event_boot(struct user_event *uev, struct event *event)
+{
+ struct device_handler *handler = uev->handler;
+ struct boot_command *cmd = talloc(handler, struct boot_command);
+
+ cmd->option_id = talloc_strdup(cmd, event_get_param(event, "id"));
+ cmd->boot_image_file = talloc_strdup(cmd, event_get_param(event, "image"));
+ cmd->initrd_file = talloc_strdup(cmd, event_get_param(event, "initrd"));
+ cmd->dtb_file = talloc_strdup(cmd, event_get_param(event, "dtb"));
+ cmd->boot_args = talloc_strdup(cmd, event_get_param(event, "args"));
+
+ device_handler_boot(handler, cmd);
+
+ talloc_free(cmd);
+
+ return 0;
+}
+
+static int user_event_sync(struct user_event *uev, struct event *event)
+{
+ struct device_handler *handler = uev->handler;
+
+ if (strncasecmp(event->device, "all", strlen("all")) != 0)
+ device_sync_snapshots(handler, event->device);
+ else
+ device_sync_snapshots(handler, NULL);
+
+ return 0;