+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
#include <unistd.h>
#include "procd.h"
INSTANCE_ATTR_COMMAND,
INSTANCE_ATTR_ENV,
INSTANCE_ATTR_DATA,
+ INSTANCE_ATTR_NETDEV,
__INSTANCE_ATTR_MAX
};
[INSTANCE_ATTR_COMMAND] = { "command", BLOBMSG_TYPE_ARRAY },
[INSTANCE_ATTR_ENV] = { "env", BLOBMSG_TYPE_TABLE },
[INSTANCE_ATTR_DATA] = { "data", BLOBMSG_TYPE_TABLE },
+ [INSTANCE_ATTR_NETDEV] = { "netdev", BLOBMSG_TYPE_ARRAY },
+};
+
+struct instance_netdev {
+ struct blobmsg_list_node node;
+ int ifindex;
};
static void
if (!blobmsg_list_equal(&in->data, &in_new->data))
return true;
+ if (!blobmsg_list_equal(&in->netdev, &in_new->netdev))
+ return true;
+
return false;
}
+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)
{
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;
}
{
blobmsg_list_free(&in->env);
blobmsg_list_free(&in->data);
+ blobmsg_list_free(&in->netdev);
}
static void
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;
+ in->config = in_src->config;
+ in_src->config = NULL;
}
bool
{
bool changed = instance_config_changed(in, in_new);
- in->config = in_new->config;
if (!changed)
return false;
in->timeout.cb = instance_timeout;
in->proc.cb = instance_exit;
+ blobmsg_list_init(&in->netdev, struct instance_netdev, node, instance_netdev_cmp);
blobmsg_list_simple_init(&in->env);
blobmsg_list_simple_init(&in->data);
in->valid = instance_config_parse(in);
#include "utils.h"
void
-__blobmsg_list_init(struct blobmsg_list *list, int offset, int len)
+__blobmsg_list_init(struct blobmsg_list *list, int offset, int len, blobmsg_list_cmp cmp)
{
avl_init(&list->avl, avl_strcmp, false, NULL);
list->node_offset = offset;
list->node_len = len;
+ list->cmp = cmp;
}
int
int rem = len;
__blob_for_each_attr(cur, data, rem) {
- if (!blobmsg_check_attr(cur, true))
+ if (!blobmsg_check_attr(cur, !array))
continue;
ptr = calloc(1, list->node_len);
void *ptr;
avl_remove_all_elements(&src->avl, node, avl, tmp) {
- if (!avl_insert(&list->avl, &node->avl)) {
+ if (avl_insert(&list->avl, &node->avl)) {
ptr = ((char *) node - list->node_offset);
free(ptr);
}
if (memcmp(n1->data, n2->data, len) != 0)
return false;
+ if (l1->cmp && !l1->cmp(n1, n2))
+ return false;
+
if (!count)
break;
#include <libubox/blob.h>
#include <libubox/blobmsg.h>
+struct blobmsg_list_node {
+ struct avl_node avl;
+ struct blob_attr *data;
+};
+
+typedef bool (*blobmsg_list_cmp)(struct blobmsg_list_node *l1, struct blobmsg_list_node *l2);
+
struct blobmsg_list {
struct avl_tree avl;
int node_offset;
int node_len;
-};
-struct blobmsg_list_node {
- struct avl_node avl;
- struct blob_attr *data;
+ blobmsg_list_cmp cmp;
};
#define blobmsg_list_simple_init(list) \
- __blobmsg_list_init(list, 0, sizeof(struct blobmsg_list_node))
+ __blobmsg_list_init(list, 0, sizeof(struct blobmsg_list_node), NULL)
-#define blobmsg_list_init(list, type, field) \
- __blobmsg_list_init(list, offsetof(type, field), sizeof(type))
+#define blobmsg_list_init(list, type, field, cmp) \
+ __blobmsg_list_init(list, offsetof(type, field), sizeof(type), cmp)
#define blobmsg_list_for_each(list, element) \
avl_for_each_element(&(list)->avl, element, avl)
-void __blobmsg_list_init(struct blobmsg_list *list, int offset, int len);
+void __blobmsg_list_init(struct blobmsg_list *list, int offset, int len, blobmsg_list_cmp cmp);
int blobmsg_list_fill(struct blobmsg_list *list, void *data, int len, bool array);
void blobmsg_list_free(struct blobmsg_list *list);
bool blobmsg_list_equal(struct blobmsg_list *l1, struct blobmsg_list *l2);