diff options
-rw-r--r-- | interface.c | 61 | ||||
-rw-r--r-- | interface.h | 14 | ||||
-rw-r--r-- | ubus.c | 27 |
3 files changed, 97 insertions, 5 deletions
diff --git a/interface.c b/interface.c index d45f2d5..52d30fc 100644 --- a/interface.c +++ b/interface.c @@ -7,7 +7,53 @@ LIST_HEAD(interfaces); -static int interface_event(struct interface *iface, enum interface_event ev) +static void +clear_interface_errors(struct interface *iface) +{ + struct interface_error *error, *tmp; + + list_for_each_entry_safe(error, tmp, &iface->errors, list) { + list_del(&error->list); + free(error); + } +} + +void interface_add_error(struct interface *iface, const char *subsystem, + const char *code, const char **data, int n_data) +{ + struct interface_error *error; + int i, len = 0; + int *datalen; + char *dest; + + if (n_data) { + len = n_data * sizeof(char *); + datalen = alloca(len); + for (i = 0; i < n_data; i++) { + datalen[i] = strlen(data[i]) + 1; + len += datalen[i]; + } + } + + error = calloc(1, sizeof(*error) + sizeof(char *) + len); + if (!error) + return; + + list_add_tail(&error->list, &iface->errors); + error->subsystem = subsystem; + error->code = code; + + dest = (char *) &error->data[n_data + 1]; + for (i = 0; i < n_data; i++) { + error->data[i] = dest; + memcpy(dest, data[i], datalen[i]); + dest += datalen[i]; + } + error->data[n_data] = NULL; +} + +static int +interface_event(struct interface *iface, enum interface_event ev) { if (!iface->state || !iface->state->event) return 0; @@ -35,6 +81,8 @@ __set_interface_up(struct interface *iface) static void __set_interface_down(struct interface *iface) { + clear_interface_errors(iface); + if (!iface->up) return; @@ -87,6 +135,8 @@ alloc_interface(const char *name) iface->l3_iface = &iface->main_dev; strncpy(iface->name, name, sizeof(iface->name) - 1); list_add(&iface->list, &interfaces); + INIT_LIST_HEAD(&iface->errors); + netifd_ubus_add_interface(iface); return iface; @@ -148,6 +198,11 @@ set_interface_up(struct interface *iface) { iface->autostart = true; + if (!iface->active) { + interface_add_error(iface, "interface", "NO_DEVICE", NULL, 0); + return -1; + } + if (iface->up || !iface->active) return -1; @@ -159,10 +214,6 @@ int set_interface_down(struct interface *iface) { iface->autostart = false; - - if (!iface->up) - return -1; - __set_interface_down(iface); return 0; diff --git a/interface.h b/interface.h index 0fd70d7..b3a86f2 100644 --- a/interface.h +++ b/interface.h @@ -19,6 +19,14 @@ struct interface_proto_state { void (*free)(struct interface *, struct interface_proto_state *); }; +struct interface_error { + struct list_head list; + + const char *subsystem; + const char *code; + const char *data[]; +}; + /* * interface configuration */ @@ -45,6 +53,9 @@ struct interface { /* primary protocol state */ struct interface_proto_state *state; + /* errors/warnings while trying to bring up the interface */ + struct list_head errors; + struct ubus_object ubus; }; @@ -58,6 +69,9 @@ int set_interface_down(struct interface *iface); int interface_add_link(struct interface *iface, struct device *llif); void interface_remove_link(struct interface *iface, struct device *llif); +void interface_add_error(struct interface *iface, const char *subsystem, + const char *code, const char **data, int n_data); + int interface_attach_bridge(struct interface *iface, struct uci_section *s); #endif @@ -110,6 +110,30 @@ 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) @@ -142,6 +166,9 @@ 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; |