+static void netns_updown(struct ubus_context *ctx, const char *name, bool start, int netns_fd)
+{
+ static struct blob_buf req;
+ uint32_t id;
+
+ if (!ctx)
+ return;
+
+ blob_buf_init(&req, 0);
+ if (name)
+ blobmsg_add_string(&req, "jail", name);
+
+ blobmsg_add_u8(&req, "start", start);
+
+ if (ubus_lookup_id(ctx, "network", &id) ||
+ ubus_invoke_fd(ctx, id, "netns_updown", req.head, NULL, NULL, 3000, netns_fd)) {
+ INFO("ubus request failed\n");
+ }
+
+ blob_buf_free(&req);
+}
+
+static void jail_network_reload(struct uloop_timeout *t)
+{
+ uint32_t id;
+
+ if (!netifd_ubus_ctx)
+ return;
+
+ if (gen_jail_uci_network())
+ return;
+
+ if (ubus_lookup_id(netifd_ubus_ctx, "network", &id))
+ return;
+
+ ubus_invoke(netifd_ubus_ctx, id, "reload", NULL, NULL, NULL, 3000);
+}
+
+static const struct blobmsg_policy service_watch_policy = { "config", BLOBMSG_TYPE_STRING };
+static struct uloop_timeout jail_network_reload_timeout = { .cb = jail_network_reload, };
+
+static int config_watch_notify_cb(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *attr;
+ const char *config;
+
+ if (strcmp(method, "config.change"))
+ return 0;
+
+ blobmsg_parse(&service_watch_policy, 1, &attr, blob_data(msg), blob_len(msg));
+ if (!attr)
+ return 1;
+
+ config = blobmsg_get_string(attr);
+ if (strcmp(config, "network"))
+ return 0;
+
+ uloop_timeout_add(&jail_network_reload_timeout);
+
+ return 0;
+}
+
+static void watch_ubus_service(void)
+{
+ uint32_t id;
+
+ config_watch_subscribe.cb = config_watch_notify_cb;
+ if (ubus_register_subscriber(ctx, &config_watch_subscribe)) {
+ ERROR("failed to register ubus subscriber\n");
+ return;
+ }
+
+ if (ubus_lookup_id(ctx, "service", &id))
+ return;
+
+ if (!ubus_subscribe(ctx, &config_watch_subscribe, id))
+ return;
+
+ ERROR("failed to subscribe %d\n", id);
+}
+