X-Git-Url: https://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=discover%2Fudev.c;h=0c3da66a6eeaa5347ae7ca137e57bb6779c714e8;hp=f4754b1662b89517f159dbfd0dd265a696501d31;hb=refs%2Ftags%2Fv1.10.4;hpb=515d2f03bae8d5617ee3bce5a46287203f7215c2 diff --git a/discover/udev.c b/discover/udev.c index f4754b1..0c3da66 100644 --- a/discover/udev.c +++ b/discover/udev.c @@ -27,6 +27,7 @@ #include "device-handler.h" #include "cdrom.h" #include "devmapper.h" +#include "network.h" /* We set a default monitor buffer size, as we may not process monitor * events while performing device discvoery. systemd uses a 128M buffer, so @@ -80,11 +81,11 @@ static void udev_setup_device_params(struct udev_device *udev, static void lvm_vg_search(struct device_handler *handler) { if (process_run_simple(handler, pb_system_apps.vgscan, "-qq", NULL)) - pb_log("%s: Failed to execute vgscan\n", __func__); + pb_log_fn("Failed to execute vgscan\n"); if (process_run_simple(handler, pb_system_apps.vgchange, "-ay", "-qq", NULL)) - pb_log("%s: Failed to execute vgchange\n", __func__); + pb_log_fn("Failed to execute vgchange\n"); } static int udev_handle_block_add(struct pb_udev *udev, struct udev_device *dev, @@ -105,7 +106,7 @@ static int udev_handle_block_add(struct pb_udev *udev, struct udev_device *dev, "swap", NULL, }; - bool cdrom, usb; + bool cdrom, usb, luks = false; typestr = udev_device_get_devtype(dev); if (!typestr) { @@ -141,11 +142,18 @@ static int udev_handle_block_add(struct pb_udev *udev, struct udev_device *dev, } } - /* Ignore any device mapper devices that aren't logical volumes */ + /* + * Ignore any device mapper devices that aren't logical volumes or + * opened encrypted devices + */ devname = udev_device_get_property_value(dev, "DM_NAME"); - if (devname && ! udev_device_get_property_value(dev, "DM_LV_NAME")) { - pb_debug("SKIP: dm-device %s\n", devname); - return 0; + if (devname) { + if (device_handler_found_crypt_device(udev->handler, devname)) { + luks = true; + } else if (!udev_device_get_property_value(dev, "DM_LV_NAME")) { + pb_debug("SKIP: dm-device %s\n", devname); + return 0; + } } type = udev_device_get_property_value(dev, "ID_FS_TYPE"); @@ -215,21 +223,99 @@ static int udev_handle_block_add(struct pb_udev *udev, struct udev_device *dev, usb = !!udev_device_get_property_value(dev, "ID_USB_DRIVER"); if (cdrom) ddev->device->type = DEVICE_TYPE_OPTICAL; + else if (strncmp(type, "crypto_LUKS", strlen("crypto_LUKS")) == 0) + ddev->device->type = DEVICE_TYPE_LUKS; else ddev->device->type = usb ? DEVICE_TYPE_USB : DEVICE_TYPE_DISK; udev_setup_device_params(dev, ddev); + /* + * Don't perform discovery on encrypted devices, just register and + * notify clients. + */ + if (ddev->device->type == DEVICE_TYPE_LUKS) { + pb_log("Notifying clients about encrypted device %s\n", + name); + device_handler_add_encrypted_dev(udev->handler, ddev); + return 0; + } + /* Create a snapshot for all disk devices */ if ((ddev->device->type == DEVICE_TYPE_DISK || ddev->device->type == DEVICE_TYPE_USB)) devmapper_init_snapshot(udev->handler, ddev); + /* Note if this is an opened LUKS device */ + ddev->crypt_device = luks; + device_handler_discover(udev->handler, ddev); return 0; } +/* + * Mark valid interfaces as 'ready'. + * The udev_enumerate_add_match_is_initialized() filter in udev_enumerate() + * ensures that any device we see is properly initialized by udev (eg. interface + * names); here we check that the properties are sane and mark the interface + * as ready for configuration in discover/network. + */ +static int udev_check_interface_ready(struct device_handler *handler, + struct udev_device *dev) +{ + const char *name, *ifindex, *interface, *mac_name; + uint8_t *mac; + char byte[3]; + unsigned int i, j; + + + name = udev_device_get_sysname(dev); + if (!name) { + pb_debug("udev_device_get_sysname failed\n"); + return -1; + } + + ifindex = udev_device_get_property_value(dev, "IFINDEX"); + interface = udev_device_get_property_value(dev, "INTERFACE"); + mac_name = udev_device_get_property_value(dev, "ID_NET_NAME_MAC"); + + /* Physical interfaces should have all of these properties */ + if (!ifindex || !interface || !mac_name) { + pb_debug("%s: interface %s missing properties\n", + __func__, name); + return -1; + } + + /* ID_NET_NAME_MAC format is enxMACADDR */ + if (strlen(mac_name) < 15) { + pb_debug("%s: Unexpected MAC format: %s\n", + __func__, mac_name); + return -1; + } + + mac = talloc_array(handler, uint8_t, HWADDR_SIZE); + if (!mac) + return -1; + + /* + * ID_NET_NAME_MAC is not a conventionally formatted MAC + * string - convert it before passing it to network.c + */ + byte[2] = '\0'; + for (i = strlen("enx"), j = 0; + i < strlen(mac_name) && j < HWADDR_SIZE; i += 2) { + memcpy(byte, &mac_name[i], 2); + mac[j++] = strtoul(byte, NULL, 16); + } + + network_mark_interface_ready(handler, + atoi(ifindex), interface, mac, HWADDR_SIZE); + + talloc_free(mac); + return 0; +} + static int udev_handle_dev_add(struct pb_udev *udev, struct udev_device *dev) { const char *subsys; @@ -247,6 +333,10 @@ static int udev_handle_dev_add(struct pb_udev *udev, struct udev_device *dev) return -1; } + /* If we see a net device, check if it is ready to be used */ + if (!strncmp(subsys, "net", strlen("net"))) + return udev_check_interface_ready(udev->handler, dev); + if (device_lookup_by_id(udev->handler, name)) { pb_debug("device %s is already present?\n", name); return -1; @@ -324,10 +414,16 @@ static bool udev_handle_cdrom_events(struct pb_udev *udev, static int udev_handle_dev_change(struct pb_udev *udev, struct udev_device *dev) { struct discover_device *ddev; + const char *subsys; const char *name; int rc = 0; name = udev_device_get_sysname(dev); + subsys = udev_device_get_subsystem(dev); + + /* If we see a net device, check if it is ready to be used */ + if (!strncmp(subsys, "net", strlen("net"))) + return udev_check_interface_ready(udev->handler, dev); ddev = device_lookup_by_id(udev->handler, name); @@ -392,6 +488,12 @@ static int udev_enumerate(struct udev *udev) goto fail; } + result = udev_enumerate_add_match_subsystem(enumerate, "net"); + if (result) { + pb_log("udev_enumerate_add_match_subsystem failed\n"); + goto fail; + } + result = udev_enumerate_add_match_is_initialized(enumerate); if (result) { pb_log("udev_enumerate_add_match_is_initialised failed\n"); @@ -449,6 +551,14 @@ static int udev_setup_monitor(struct udev *udev, struct udev_monitor **monitor) goto out_err; } + result = udev_monitor_filter_add_match_subsystem_devtype(m, "net", + NULL); + + if (result) { + pb_log("udev_monitor_filter_add_match_subsystem_devtype failed\n"); + goto out_err; + } + result = udev_monitor_enable_receiving(m); if (result) {