summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--instance.c50
-rw-r--r--instance.h1
-rw-r--r--utils.c10
-rw-r--r--utils.h20
4 files changed, 69 insertions, 12 deletions
diff --git a/instance.c b/instance.c
index c70fff6..19454c7 100644
--- a/instance.c
+++ b/instance.c
@@ -1,3 +1,6 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
#include <unistd.h>
#include "procd.h"
@@ -8,6 +11,7 @@ enum {
INSTANCE_ATTR_COMMAND,
INSTANCE_ATTR_ENV,
INSTANCE_ATTR_DATA,
+ INSTANCE_ATTR_NETDEV,
__INSTANCE_ATTR_MAX
};
@@ -15,6 +19,12 @@ static const struct blobmsg_policy instance_attr[__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
@@ -116,10 +126,30 @@ instance_config_changed(struct service_instance *in, struct service_instance *in
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)
{
struct blob_attr *tb[__INSTANCE_ATTR_MAX];
@@ -149,15 +179,28 @@ 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;
}
@@ -166,6 +209,7 @@ instance_config_cleanup(struct service_instance *in)
{
blobmsg_list_free(&in->env);
blobmsg_list_free(&in->data);
+ blobmsg_list_free(&in->netdev);
}
static void
@@ -174,8 +218,12 @@ instance_config_move(struct service_instance *in, struct service_instance *in_sr
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
@@ -183,7 +231,6 @@ instance_update(struct service_instance *in, struct service_instance *in_new)
{
bool changed = instance_config_changed(in, in_new);
- in->config = in_new->config;
if (!changed)
return false;
@@ -211,6 +258,7 @@ instance_init(struct service_instance *in, struct service *s, struct blob_attr *
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);
diff --git a/instance.h b/instance.h
index 011cd9c..59e887c 100644
--- a/instance.h
+++ b/instance.h
@@ -19,6 +19,7 @@ struct service_instance {
struct blob_attr *command;
struct blobmsg_list env;
struct blobmsg_list data;
+ struct blobmsg_list netdev;
};
void instance_start(struct service_instance *in);
diff --git a/utils.c b/utils.c
index 0f9ce74..628136f 100644
--- a/utils.c
+++ b/utils.c
@@ -3,11 +3,12 @@
#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
@@ -21,7 +22,7 @@ blobmsg_list_fill(struct blobmsg_list *list, void *data, int len, bool array)
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);
@@ -52,7 +53,7 @@ blobmsg_list_move(struct blobmsg_list *list, struct blobmsg_list *src)
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);
}
@@ -93,6 +94,9 @@ blobmsg_list_equal(struct blobmsg_list *l1, struct blobmsg_list *l2)
if (memcmp(n1->data, n2->data, len) != 0)
return false;
+ if (l1->cmp && !l1->cmp(n1, n2))
+ return false;
+
if (!count)
break;
diff --git a/utils.h b/utils.h
index e20169a..360f9f1 100644
--- a/utils.h
+++ b/utils.h
@@ -5,27 +5,31 @@
#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);