+ return 0;
+}
+
+static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
+ Manager *m = userdata;
+
+ assert(s);
+ assert(m);
+
+ m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
+
+ manager_connect_bus(m);
+
+ return 0;
+}
+
+static int manager_reset_all(Manager *m) {
+ Link *link;
+ Iterator i;
+ int r;
+
+ assert(m);
+
+ HASHMAP_FOREACH(link, m->links, i) {
+ r = link_carrier_reset(link);
+ if (r < 0)
+ log_link_warning_errno(link, r, "could not reset carrier: %m");
+ }
+
+ return 0;
+}
+
+static int match_prepare_for_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
+ Manager *m = userdata;
+ int b, r;
+
+ assert(bus);
+ assert(bus);
+
+ r = sd_bus_message_read(message, "b", &b);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m");
+ return 0;
+ }
+
+ if (b)
+ return 0;
+
+ log_debug("Coming back from suspend, resetting all connections...");
+
+ manager_reset_all(m);
+
+ return 0;
+}
+
+int manager_connect_bus(Manager *m) {
+ int r;
+
+ assert(m);
+
+ r = sd_bus_default_system(&m->bus);
+ if (r == -ENOENT) {
+ /* We failed to connect? Yuck, we must be in early
+ * boot. Let's try in 5s again. As soon as we have
+ * kdbus we can stop doing this... */
+
+ log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
+
+ r = sd_event_add_time(m->event, &m->bus_retry_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 5*USEC_PER_SEC, 0, on_bus_retry, m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to install bus reconnect time event: %m");
+
+ return 0;
+ } if (r < 0)
+ return r;
+
+ r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
+ "type='signal',"
+ "sender='org.freedesktop.login1',"
+ "interface='org.freedesktop.login1.Manager',"
+ "member='PrepareForSleep',"
+ "path='/org/freedesktop/login1'",
+ match_prepare_for_sleep,
+ m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add match for PrepareForSleep: %m");
+
+ r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/network1", "org.freedesktop.network1.Manager", manager_vtable, m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add manager object vtable: %m");
+
+ r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/link", "org.freedesktop.network1.Link", link_vtable, link_object_find, m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add link object vtable: %m");
+
+ r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/link", link_node_enumerator, m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add link enumerator: %m");
+
+ r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/network", "org.freedesktop.network1.Network", network_vtable, network_object_find, m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add network object vtable: %m");
+
+ r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/network", network_node_enumerator, m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add network enumerator: %m");
+
+ r = sd_bus_request_name(m->bus, "org.freedesktop.network1", 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to register name: %m");
+
+ r = sd_bus_attach_event(m->bus, m->event, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to attach bus to event loop: %m");
+
+ return 0;
+}
+
+static int manager_udev_process_link(Manager *m, struct udev_device *device) {
+ Link *link = NULL;
+ int r, ifindex;
+
+ assert(m);
+ assert(device);
+
+ if (!streq_ptr(udev_device_get_action(device), "add"))
+ return 0;
+
+ ifindex = udev_device_get_ifindex(device);
+ if (ifindex <= 0) {
+ log_debug("ignoring udev ADD event for device with invalid ifindex");
+ return 0;
+ }
+
+ r = link_get(m, ifindex, &link);
+ if (r == -ENODEV)
+ return 0;
+ else if (r < 0)
+ return r;
+
+ r = link_initialized(link, device);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+ Manager *m = userdata;
+ struct udev_monitor *monitor = m->udev_monitor;
+ _cleanup_udev_device_unref_ struct udev_device *device = NULL;
+
+ device = udev_monitor_receive_device(monitor);
+ if (!device)
+ return -ENOMEM;
+
+ manager_udev_process_link(m, device);
+ return 0;
+}
+
+static int manager_connect_udev(Manager *m) {
+ int r;
+
+ /* udev does not initialize devices inside containers,
+ * so we rely on them being already initialized before
+ * entering the container */
+ if (detect_container(NULL) > 0)
+ return 0;
+