+static bool
+instance_netdev_cmp(struct blobmsg_list_node *l1, struct blobmsg_list_node *l2)
+{
+ struct instance_netdev *n1 = container_of(l1, struct instance_netdev, node);
+ struct instance_netdev *n2 = container_of(l2, struct instance_netdev, node);
+
+ return n1->ifindex == n2->ifindex;
+}
+
+static void
+instance_netdev_update(struct blobmsg_list_node *l)
+{
+ struct instance_netdev *n = container_of(l, struct instance_netdev, node);
+
+ n->ifindex = if_nametoindex(n->node.avl.key);
+}
+
+static bool
+instance_config_parse(struct service_instance *in)
+{
+ struct blob_attr *tb[__INSTANCE_ATTR_MAX];
+ struct blob_attr *cur, *cur2;
+ int argc = 0;
+ int rem;
+
+ blobmsg_parse(instance_attr, __INSTANCE_ATTR_MAX, tb,
+ blobmsg_data(in->config), blobmsg_data_len(in->config));
+
+ cur = tb[INSTANCE_ATTR_COMMAND];
+ if (!cur)
+ return false;
+
+ if (!blobmsg_check_attr_list(cur, BLOBMSG_TYPE_STRING))
+ return false;
+
+ blobmsg_for_each_attr(cur2, cur, rem) {
+ argc++;
+ break;
+ }
+ if (!argc)
+ return false;
+
+ in->command = cur;
+
+ if ((cur = tb[INSTANCE_ATTR_NICE])) {
+ in->nice = (int8_t) blobmsg_get_u32(cur);
+ if (in->nice < -20 || in->nice > 20)
+ return false;
+ }
+
+ if ((cur = tb[INSTANCE_ATTR_ENV])) {
+ if (!blobmsg_check_attr_list(cur, BLOBMSG_TYPE_STRING))
+ return false;
+
+ blobmsg_list_fill(&in->env, blobmsg_data(cur), blobmsg_data_len(cur), false);
+ }
+
+ if ((cur = tb[INSTANCE_ATTR_DATA])) {
+ if (!blobmsg_check_attr_list(cur, BLOBMSG_TYPE_STRING))
+ return false;
+
+ blobmsg_list_fill(&in->data, blobmsg_data(cur), blobmsg_data_len(cur), false);
+ }
+
+ if ((cur = tb[INSTANCE_ATTR_NETDEV])) {
+ struct blobmsg_list_node *ndev;
+
+ if (!blobmsg_check_attr_list(cur, BLOBMSG_TYPE_STRING))
+ return false;
+
+ blobmsg_list_fill(&in->netdev, blobmsg_data(cur), blobmsg_data_len(cur), true);
+ blobmsg_list_for_each(&in->netdev, ndev)
+ instance_netdev_update(ndev);
+ }
+
+ return true;
+}
+
+static void
+instance_config_cleanup(struct service_instance *in)
+{
+ blobmsg_list_free(&in->env);
+ blobmsg_list_free(&in->data);
+ blobmsg_list_free(&in->netdev);
+}
+
+static void
+instance_config_move(struct service_instance *in, struct service_instance *in_src)
+{
+ instance_config_cleanup(in);
+ blobmsg_list_move(&in->env, &in_src->env);
+ blobmsg_list_move(&in->data, &in_src->data);
+ blobmsg_list_move(&in->netdev, &in_src->netdev);
+ in->command = in_src->command;
+ in->name = in_src->name;
+ in->node.avl.key = in_src->node.avl.key;
+
+ free(in->config);
+ in->config = in_src->config;
+ in_src->config = NULL;
+}
+