fix duplicate device release on interface down
[project/netifd.git] / ubus.c
diff --git a/ubus.c b/ubus.c
index 601a116..72cf0e5 100644 (file)
--- a/ubus.c
+++ b/ubus.c
@@ -1,6 +1,7 @@
 #include <string.h>
 
 #include "netifd.h"
+#include "interface.h"
 #include "ubus.h"
 
 static struct ubus_context *ctx = NULL;
@@ -8,19 +9,6 @@ static struct blob_buf b;
 
 /* global object */
 
-static const struct ubus_signature main_object_sig[] = {
-       UBUS_METHOD_START("add_device"),
-       UBUS_FIELD(STRING, "name"),
-       UBUS_METHOD_END(),
-
-       UBUS_METHOD_START("del_device"),
-       UBUS_FIELD(STRING, "name"),
-       UBUS_METHOD_END(),
-};
-
-static struct ubus_object_type main_object_type =
-       UBUS_OBJECT_TYPE("netifd", main_object_sig);
-
 enum {
        DEV_NAME,
        DEV_FORCE,
@@ -58,10 +46,13 @@ static int netifd_handle_device(struct ubus_context *ctx, struct ubus_object *ob
 }
 
 static struct ubus_method main_object_methods[] = {
-       { .name = "add_device", .handler = netifd_handle_device },
-       { .name = "del_device", .handler = netifd_handle_device },
+       UBUS_METHOD("add_device", netifd_handle_device, dev_policy),
+       UBUS_METHOD("del_device", netifd_handle_device, dev_policy),
 };
 
+static struct ubus_object_type main_object_type =
+       UBUS_OBJECT_TYPE("netifd", main_object_methods);
+
 static struct ubus_object main_object = {
        .name = "network.interface",
        .type = &main_object_type,
@@ -95,17 +86,6 @@ void netifd_ubus_done(void)
 
 
 /* per-interface object */
-static const struct ubus_signature iface_object_sig[] = {
-       UBUS_METHOD_START("up"),
-       UBUS_METHOD_END(),
-
-       UBUS_METHOD_START("down"),
-       UBUS_METHOD_END(),
-};
-
-static struct ubus_object_type iface_object_type =
-       UBUS_OBJECT_TYPE("netifd_iface", iface_object_sig);
-
 
 static int netifd_handle_up(struct ubus_context *ctx, struct ubus_object *obj,
                            struct ubus_request_data *req, const char *method,
@@ -131,16 +111,46 @@ static int netifd_handle_down(struct ubus_context *ctx, struct ubus_object *obj,
        return 0;
 }
 
+static void netifd_add_interface_errors(struct blob_buf *b, struct interface *iface)
+{
+       struct interface_error *error;
+       void *e, *e2, *e3;
+       int i;
+
+       e = blobmsg_open_array(b, "errors");
+       list_for_each_entry(error, &iface->errors, list) {
+               e2 = blobmsg_open_table(b, NULL);
+
+               blobmsg_add_string(b, "subsystem", error->subsystem);
+               blobmsg_add_string(b, "code", error->code);
+               if (error->data[0]) {
+                       e3 = blobmsg_open_array(b, "data");
+                       for (i = 0; error->data[i]; i++)
+                               blobmsg_add_string(b, NULL, error->data[i]);
+                       blobmsg_close_array(b, e3);
+               }
+
+               blobmsg_close_table(b, e2);
+       }
+       blobmsg_close_array(b, e);
+}
+
 static int netifd_handle_status(struct ubus_context *ctx, struct ubus_object *obj,
                                struct ubus_request_data *req, const char *method,
                                struct blob_attr *msg)
 {
+       static const char *iface_state[] = {
+               [IFS_SETUP] = "setup",
+               [IFS_UP] = "up",
+               [IFS_TEARDOWN] = "teardown",
+               [IFS_DOWN] = "down",
+       };
        struct interface *iface;
 
        iface = container_of(obj, struct interface, ubus);
 
        blob_buf_init(&b, 0);
-       blobmsg_add_u8(&b, "up", iface->up);
+       blobmsg_add_string(&b, "state", iface_state[iface->state]);
        blobmsg_add_u8(&b, "active", iface->active);
        blobmsg_add_u8(&b, "autostart", iface->autostart);
        if (iface->main_dev.dev) {
@@ -163,17 +173,24 @@ static int netifd_handle_status(struct ubus_context *ctx, struct ubus_object *ob
                blobmsg_close_table(&b, devinfo);
        }
 
+       if (!list_is_empty(&iface->errors))
+               netifd_add_interface_errors(&b, iface);
+
        ubus_send_reply(ctx, req, b.head);
 
        return 0;
 }
 
+
 static struct ubus_method iface_object_methods[] = {
        { .name = "up", .handler = netifd_handle_up },
        { .name = "down", .handler = netifd_handle_down },
        { .name = "status", .handler = netifd_handle_status },
 };
 
+static struct ubus_object_type iface_object_type =
+       UBUS_OBJECT_TYPE("netifd_iface", iface_object_methods);
+
 
 void netifd_ubus_add_interface(struct interface *iface)
 {