diff options
author | Felix Fietkau <nbd@openwrt.org> | 2012-03-23 15:25:39 +0200 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2012-03-23 15:45:28 +0200 |
commit | 76d5b041afff56375bb88a18eff33e50acceb1d8 (patch) | |
tree | e2b7fe20ab497c4ea971141b3c1b323604a52492 | |
parent | b7d1c27b752df3e6c5dfe6a5b789d6cb0c87d0f6 (diff) |
add support for attaching arbitrary state data to interfaces
-rw-r--r-- | interface.c | 38 | ||||
-rw-r--r-- | interface.h | 10 | ||||
-rw-r--r-- | ubus.c | 30 |
3 files changed, 77 insertions, 1 deletions
diff --git a/interface.c b/interface.c index 902f55b..c5addea 100644 --- a/interface.c +++ b/interface.c @@ -81,6 +81,42 @@ void interface_add_error(struct interface *iface, const char *subsystem, } static void +interface_data_del(struct interface *iface, struct interface_data *data) +{ + avl_delete(&iface->data, &data->node); + free(data); +} + +static void +interface_data_flush(struct interface *iface) +{ + struct interface_data *d, *tmp; + + avl_for_each_element_safe(&iface->data, d, node, tmp) + interface_data_del(iface, d); +} + +int +interface_add_data(struct interface *iface, const struct blob_attr *data) +{ + struct interface_data *n, *o; + + if (!blobmsg_check_attr(data, true)) + return UBUS_STATUS_INVALID_ARGUMENT; + + n = calloc(1, sizeof(*data) + blob_pad_len(data)); + memcpy(n->data, data, blob_pad_len(data)); + n->node.key = blobmsg_name(data); + + o = avl_find_element(&iface->data, n->node.key, o, node); + if (o) + interface_data_del(iface, o); + + avl_insert(&iface->data, &n->node); + return 0; +} + +static void interface_event(struct interface *iface, enum interface_event ev) { struct interface_user *dep, *tmp; @@ -98,6 +134,7 @@ interface_flush_state(struct interface *iface) device_release(&iface->main_dev); if (iface->l3_dev.dev) device_release(&iface->l3_dev); + interface_data_flush(iface); } static void @@ -318,6 +355,7 @@ interface_init(struct interface *iface, const char *name, INIT_LIST_HEAD(&iface->hotplug_list); interface_ip_init(&iface->proto_ip, iface); interface_ip_init(&iface->config_ip, iface); + avl_init(&iface->data, avl_strcmp, false, NULL); iface->config_ip.enabled = false; iface->main_dev.cb = interface_cb; diff --git a/interface.h b/interface.h index b2ecd23..5e3f383 100644 --- a/interface.h +++ b/interface.h @@ -51,6 +51,11 @@ struct interface_ip_settings { struct vlist_simple_tree dns_search; }; +struct interface_data { + struct avl_node node; + struct blob_attr data[]; +}; + /* * interface configuration */ @@ -92,6 +97,9 @@ struct interface { /* errors/warnings while trying to bring up the interface */ struct list_head errors; + /* extra data provided by protocol handlers or modules */ + struct avl_tree data; + struct uloop_timeout remove_timer; struct ubus_object ubus; }; @@ -123,6 +131,8 @@ int interface_remove_link(struct interface *iface, struct device *dev); void interface_add_error(struct interface *iface, const char *subsystem, const char *code, const char **data, int n_data); +int interface_add_data(struct interface *iface, const struct blob_attr *data); + void interface_update_start(struct interface *iface); void interface_update_complete(struct interface *iface); @@ -289,6 +289,7 @@ netifd_handle_status(struct ubus_context *ctx, struct ubus_object *obj, struct blob_attr *msg) { struct interface *iface; + struct interface_data *data; struct device *dev; void *a; @@ -321,6 +322,12 @@ netifd_handle_status(struct ubus_context *ctx, struct ubus_object *obj, blobmsg_close_array(&b, a); } + a = blobmsg_open_table(&b, "data"); + avl_for_each_element(&iface->data, data, node) + blob_put(&b, blob_id(data->data), blob_data(data->data), blob_len(data->data)); + + blobmsg_close_table(&b, a); + if (!list_is_empty(&iface->errors)) netifd_add_interface_errors(&b, iface); @@ -425,6 +432,26 @@ netifd_handle_iface_prepare(struct ubus_context *ctx, struct ubus_object *obj, return ops->prepare(dev); } +static int +netifd_handle_set_data(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct interface *iface; + struct blob_attr *cur; + int rem, ret; + + iface = container_of(obj, struct interface, ubus); + + blob_for_each_attr(cur, msg, rem) { + ret = interface_add_data(iface, cur); + if (ret) + return ret; + } + + return 0; +} + static struct ubus_method iface_object_methods[] = { { .name = "up", .handler = netifd_handle_up }, { .name = "down", .handler = netifd_handle_down }, @@ -433,7 +460,8 @@ static struct ubus_method iface_object_methods[] = { UBUS_METHOD("add_device", netifd_iface_handle_device, dev_policy ), UBUS_METHOD("remove_device", netifd_iface_handle_device, dev_policy ), { .name = "notify_proto", .handler = netifd_iface_notify_proto }, - { .name = "remove", .handler = netifd_iface_remove } + { .name = "remove", .handler = netifd_iface_remove }, + { .name = "set_data", .handler = netifd_handle_set_data }, }; static struct ubus_object_type iface_object_type = |