X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=ubus.c;h=bf7267239ccc7ab16625fc658f1a04cfcc015db7;hp=d24554198897ef6bb713d529e640a76227e93b91;hb=d397e8ca5dd492a1fac2e186e2a8b91ac8e463df;hpb=266d92dd83bd5bfe520f3e2838794bf9bb827c07 diff --git a/ubus.c b/ubus.c index d245541..bf72672 100644 --- a/ubus.c +++ b/ubus.c @@ -22,8 +22,9 @@ #include "proto.h" #include "ubus.h" #include "system.h" +#include "wireless.h" -static struct ubus_context *ctx = NULL; +struct ubus_context *ubus_ctx = NULL; static struct blob_buf b; static const char *ubus_path; @@ -43,8 +44,10 @@ netifd_handle_reload(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { - netifd_reload(); - return 0; + if (netifd_reload()) + return UBUS_STATUS_UNKNOWN_ERROR; + + return UBUS_STATUS_OK; } enum { @@ -126,7 +129,6 @@ netifd_add_dynamic(struct ubus_context *ctx, struct ubus_object *obj, struct blob_attr *tb[__DI_MAX]; struct interface *iface; struct blob_attr *config; - struct device *dev; blobmsg_parse(dynamic_policy, __DI_MAX, tb, blob_data(msg), blob_len(msg)); @@ -135,29 +137,25 @@ netifd_add_dynamic(struct ubus_context *ctx, struct ubus_object *obj, const char *name = blobmsg_get_string(tb[DI_NAME]); - iface = calloc(1, sizeof(*iface)); + iface = interface_alloc(name, msg); if (!iface) return UBUS_STATUS_UNKNOWN_ERROR; - interface_init(iface, name, msg, true); - iface->device_config = true; - config = blob_memdup(msg); if (!config) goto error; interface_add(iface, config); - // need to look up the interface name again, in case of config update, + // need to look up the interface name again, in case of config update + // the pointer will have changed iface = vlist_find(&interfaces, name, iface, node); if (!iface) return UBUS_STATUS_UNKNOWN_ERROR; - dev = iface->main_dev.dev; - if (!dev || !dev->default_config) - return UBUS_STATUS_UNKNOWN_ERROR; + // Set interface as dynamic + interface_set_dynamic(iface); - device_set_config(dev, dev->type, msg); return UBUS_STATUS_OK; error: @@ -203,7 +201,7 @@ netifd_dev_status(struct ubus_context *ctx, struct ubus_object *obj, blobmsg_parse(dev_policy, __DEV_MAX, tb, blob_data(msg), blob_len(msg)); if (tb[DEV_NAME]) { - dev = device_get(blobmsg_data(tb[DEV_NAME]), false); + dev = device_find(blobmsg_data(tb[DEV_NAME])); if (!dev) return UBUS_STATUS_INVALID_ARGUMENT; } @@ -289,7 +287,7 @@ netifd_handle_set_state(struct ubus_context *ctx, struct ubus_object *obj, if (!cur) return UBUS_STATUS_INVALID_ARGUMENT; - dev = device_get(blobmsg_data(cur), false); + dev = device_find(blobmsg_data(cur)); if (!dev) return UBUS_STATUS_NOT_FOUND; @@ -319,8 +317,8 @@ static struct ubus_object dev_object = { static void netifd_ubus_add_fd(void) { - ubus_add_uloop(ctx); - system_fd_set_cloexec(ctx->sock.fd); + ubus_add_uloop(ubus_ctx); + system_fd_set_cloexec(ubus_ctx->sock.fd); } static void @@ -331,13 +329,13 @@ netifd_ubus_reconnect_timer(struct uloop_timeout *timeout) }; int t = 2; - if (ubus_reconnect(ctx, ubus_path) != 0) { + if (ubus_reconnect(ubus_ctx, ubus_path) != 0) { DPRINTF("failed to reconnect, trying again in %d seconds\n", t); uloop_timeout_set(&retry, t * 1000); return; } - DPRINTF("reconnected to ubus, new id: %08x\n", ctx->local_id); + DPRINTF("reconnected to ubus, new id: %08x\n", ubus_ctx->local_id); netifd_ubus_add_fd(); } @@ -375,6 +373,19 @@ netifd_handle_down(struct ubus_context *ctx, struct ubus_object *obj, return 0; } +static int +netifd_handle_renew(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct interface *iface; + + iface = container_of(obj, struct interface, ubus); + interface_renew(iface); + + return 0; +} + static void netifd_add_interface_errors(struct blob_buf *b, struct interface *iface) { @@ -401,8 +412,7 @@ netifd_add_interface_errors(struct blob_buf *b, struct interface *iface) } static void -interface_ip_dump_address_list(struct interface_ip_settings *ip, bool v6, - bool enabled) +interface_ip_dump_address_list(struct interface_ip_settings *ip, bool v6, bool enabled) { struct device_addr *addr; char *buf; @@ -441,6 +451,9 @@ interface_ip_dump_address_list(struct interface_ip_settings *ip, bool v6, if (addr->valid_until) blobmsg_add_u32(&b, "valid", addr->valid_until - now); + if (addr->pclass) + blobmsg_add_string(&b, "class", addr->pclass); + blobmsg_close_table(&b, a); } } @@ -459,6 +472,9 @@ interface_ip_dump_route_list(struct interface_ip_settings *ip, bool enabled) if (route->enabled != enabled) continue; + if ((ip->no_defaultroute == enabled) && !route->mask) + continue; + if ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) af = AF_INET; else @@ -476,6 +492,12 @@ interface_ip_dump_route_list(struct interface_ip_settings *ip, bool enabled) inet_ntop(af, &route->nexthop, buf, buflen); blobmsg_add_string_buffer(&b); + if (route->flags & DEVROUTE_TYPE) + blobmsg_add_u32(&b, "type", route->type); + + if (route->flags & DEVROUTE_PROTO) + blobmsg_add_u32(&b, "proto", route->proto); + if (route->flags & DEVROUTE_MTU) blobmsg_add_u32(&b, "mtu", route->mtu); @@ -488,6 +510,11 @@ interface_ip_dump_route_list(struct interface_ip_settings *ip, bool enabled) if (route->valid_until) blobmsg_add_u32(&b, "valid", route->valid_until - now); + buf = blobmsg_alloc_string_buffer(&b, "source", buflen); + inet_ntop(af, &route->source, buf, buflen); + snprintf(buf + strlen(buf), buflen - strlen(buf), "/%u", route->sourcemask); + blobmsg_add_string_buffer(&b); + blobmsg_close_table(&b, r); } } @@ -585,15 +612,23 @@ interface_ip_dump_prefix_assignment_list(struct interface *iface) if (prefix->valid_until) blobmsg_add_u32(&b, "valid", prefix->valid_until - now); + void *c = blobmsg_open_table(&b, "local-address"); + if (assign->enabled) { + buf = blobmsg_alloc_string_buffer(&b, "address", buflen); + inet_ntop(AF_INET6, &assign->addr, buf, buflen); + blobmsg_add_string_buffer(&b); + + blobmsg_add_u32(&b, "mask", assign->length < 64 ? 64 : assign->length); + } + blobmsg_close_table(&b, c); + blobmsg_close_table(&b, a); } } } - static void -interface_ip_dump_dns_server_list(struct interface_ip_settings *ip, - bool enabled) +interface_ip_dump_dns_server_list(struct interface_ip_settings *ip, bool enabled) { struct dns_server *dns; int buflen = 128; @@ -610,8 +645,7 @@ interface_ip_dump_dns_server_list(struct interface_ip_settings *ip, } static void -interface_ip_dump_dns_search_list(struct interface_ip_settings *ip, - bool enabled) +interface_ip_dump_dns_search_list(struct interface_ip_settings *ip, bool enabled) { struct dns_search_domain *dns; @@ -630,28 +664,52 @@ netifd_dump_status(struct interface *iface) struct device *dev; void *a, *inactive; - blobmsg_add_string(&b, "name", iface->name); blobmsg_add_u8(&b, "up", iface->state == IFS_UP); blobmsg_add_u8(&b, "pending", iface->state == IFS_SETUP); blobmsg_add_u8(&b, "available", iface->available); blobmsg_add_u8(&b, "autostart", iface->autostart); + blobmsg_add_u8(&b, "dynamic", iface->dynamic); if (iface->state == IFS_UP) { time_t cur = system_get_rtime(); blobmsg_add_u32(&b, "uptime", cur - iface->start_time); - blobmsg_add_string(&b, "l3_device", iface->l3_dev.dev->ifname); + if (iface->l3_dev.dev) + blobmsg_add_string(&b, "l3_device", iface->l3_dev.dev->ifname); } if (iface->proto_handler) blobmsg_add_string(&b, "proto", iface->proto_handler->name); dev = iface->main_dev.dev; - if (dev && !dev->hidden && + if (dev && !dev->hidden && iface->proto_handler && !(iface->proto_handler->flags & PROTO_FLAG_NODEV)) blobmsg_add_string(&b, "device", dev->ifname); if (iface->state == IFS_UP) { + if (iface->updated) { + a = blobmsg_open_array(&b, "updated"); + + if (iface->updated & IUF_ADDRESS) + blobmsg_add_string(&b, NULL, "addresses"); + if (iface->updated & IUF_ROUTE) + blobmsg_add_string(&b, NULL, "routes"); + if (iface->updated & IUF_PREFIX) + blobmsg_add_string(&b, NULL, "prefixes"); + if (iface->updated & IUF_DATA) + blobmsg_add_string(&b, NULL, "data"); + + blobmsg_close_array(&b, a); + } + + if (iface->ip4table) + blobmsg_add_u32(&b, "ip4table", iface->ip4table); + if (iface->ip6table) + blobmsg_add_u32(&b, "ip6table", iface->ip6table); blobmsg_add_u32(&b, "metric", iface->metric); + blobmsg_add_u32(&b, "dns_metric", iface->dns_metric); + blobmsg_add_u8(&b, "delegation", !iface->proto_ip.no_delegation); + if (iface->assignment_weight) + blobmsg_add_u32(&b, "ip6weight", iface->assignment_weight); a = blobmsg_open_array(&b, "ipv4-address"); interface_ip_dump_address_list(&iface->config_ip, false, true); interface_ip_dump_address_list(&iface->proto_ip, false, true); @@ -706,11 +764,11 @@ netifd_dump_status(struct interface *iface) 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_add_blob(&b, data->data); blobmsg_close_table(&b, a); - if (!list_is_empty(&iface->errors)) + if (!list_empty(&iface->errors)) netifd_add_interface_errors(&b, iface); } @@ -728,6 +786,7 @@ netifd_handle_status(struct ubus_context *ctx, struct ubus_object *obj, return 0; } + static int netifd_handle_dump(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, @@ -739,6 +798,7 @@ netifd_handle_dump(struct ubus_context *ctx, struct ubus_object *obj, struct interface *iface; vlist_for_each_element(&interfaces, iface, node) { void *i = blobmsg_open_table(&b, NULL); + blobmsg_add_string(&b, "interface", iface->name); netifd_dump_status(iface); blobmsg_close_table(&b, i); } @@ -749,47 +809,40 @@ netifd_handle_dump(struct ubus_context *ctx, struct ubus_object *obj, return 0; } +enum { + DEV_LINK_NAME, + DEV_LINK_EXT, + __DEV_LINK_MAX, +}; + +static const struct blobmsg_policy dev_link_policy[__DEV_LINK_MAX] = { + [DEV_LINK_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING }, + [DEV_LINK_EXT] = { .name = "link-ext", .type = BLOBMSG_TYPE_BOOL }, +}; + static int netifd_iface_handle_device(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { - struct blob_attr *tb[__DEV_MAX]; + struct blob_attr *tb[__DEV_LINK_MAX]; + struct blob_attr *cur; struct interface *iface; - struct device *dev; bool add = !strncmp(method, "add", 3); - int ret; + bool link_ext = true; iface = container_of(obj, struct interface, ubus); - blobmsg_parse(dev_policy, __DEV_MAX, tb, blob_data(msg), blob_len(msg)); + blobmsg_parse(dev_link_policy, __DEV_LINK_MAX, tb, blob_data(msg), blob_len(msg)); - if (!tb[DEV_NAME]) + if (!tb[DEV_LINK_NAME]) return UBUS_STATUS_INVALID_ARGUMENT; - device_lock(); - - dev = device_get(blobmsg_data(tb[DEV_NAME]), add ? 2 : 0); - if (!dev) { - ret = UBUS_STATUS_NOT_FOUND; - goto out; - } - - if (add) { - device_set_present(dev, true); - if (iface->device_config) - device_set_config(dev, &simple_device_type, iface->config); - - system_if_apply_settings(dev, &dev->settings); - ret = interface_add_link(iface, dev); - } else { - ret = interface_remove_link(iface, dev); - } - -out: - device_unlock(); + cur = tb[DEV_LINK_EXT]; + if (cur) + link_ext = blobmsg_get_bool(cur); - return ret; + return interface_handle_link(iface, blobmsg_data(tb[DEV_LINK_NAME]), add, link_ext); } @@ -860,28 +913,21 @@ netifd_handle_set_data(struct ubus_context *ctx, struct ubus_object *obj, 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; + return interface_parse_data(iface, msg); } static struct ubus_method iface_object_methods[] = { { .name = "up", .handler = netifd_handle_up }, { .name = "down", .handler = netifd_handle_down }, + { .name = "renew", .handler = netifd_handle_renew }, { .name = "status", .handler = netifd_handle_status }, { .name = "prepare", .handler = netifd_handle_iface_prepare }, { .name = "dump", .handler = netifd_handle_dump }, - UBUS_METHOD("add_device", netifd_iface_handle_device, dev_policy ), - UBUS_METHOD("remove_device", netifd_iface_handle_device, dev_policy ), + UBUS_METHOD("add_device", netifd_iface_handle_device, dev_link_policy ), + UBUS_METHOD("remove_device", netifd_iface_handle_device, dev_link_policy ), { .name = "notify_proto", .handler = netifd_iface_notify_proto }, { .name = "remove", .handler = netifd_iface_remove }, { .name = "set_data", .handler = netifd_handle_set_data }, @@ -899,7 +945,7 @@ static struct ubus_object iface_object = { static void netifd_add_object(struct ubus_object *obj) { - int ret = ubus_add_object(ctx, obj); + int ret = ubus_add_object(ubus_ctx, obj); if (ret != 0) fprintf(stderr, "Failed to publish object '%s': %s\n", obj->name, ubus_strerror(ret)); @@ -946,6 +992,9 @@ static void netifd_add_iface_object(void) int i; methods = calloc(1, sizeof(iface_object_methods)); + if (!methods) + return; + memcpy(methods, iface_object_methods, sizeof(iface_object_methods)); iface_object.methods = methods; @@ -960,22 +1009,174 @@ static void netifd_add_iface_object(void) netifd_add_object(&iface_object); } +static struct wireless_device * +get_wdev(struct blob_attr *msg, int *ret) +{ + struct blobmsg_policy wdev_policy = { + .name = "device", + .type = BLOBMSG_TYPE_STRING, + }; + struct blob_attr *dev_attr; + struct wireless_device *wdev = NULL; + + + blobmsg_parse(&wdev_policy, 1, &dev_attr, blob_data(msg), blob_len(msg)); + if (!dev_attr) { + *ret = UBUS_STATUS_INVALID_ARGUMENT; + return NULL; + } + + wdev = vlist_find(&wireless_devices, blobmsg_data(dev_attr), wdev, node); + if (!wdev) { + *ret = UBUS_STATUS_NOT_FOUND; + return NULL; + } + + *ret = 0; + return wdev; +} + +static int +netifd_handle_wdev_up(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct wireless_device *wdev; + int ret; + + wdev = get_wdev(msg, &ret); + if (ret == UBUS_STATUS_NOT_FOUND) + return ret; + + if (wdev) { + wireless_device_set_up(wdev); + } else { + vlist_for_each_element(&wireless_devices, wdev, node) + wireless_device_set_up(wdev); + } + + return 0; +} + +static int +netifd_handle_wdev_down(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct wireless_device *wdev; + int ret; + + wdev = get_wdev(msg, &ret); + if (ret == UBUS_STATUS_NOT_FOUND) + return ret; + + if (wdev) { + wireless_device_set_down(wdev); + } else { + vlist_for_each_element(&wireless_devices, wdev, node) + wireless_device_set_down(wdev); + } + + return 0; +} + +static int +netifd_handle_wdev_status(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct wireless_device *wdev; + int ret; + + wdev = get_wdev(msg, &ret); + if (ret == UBUS_STATUS_NOT_FOUND) + return ret; + + blob_buf_init(&b, 0); + if (wdev) { + wireless_device_status(wdev, &b); + } else { + vlist_for_each_element(&wireless_devices, wdev, node) + wireless_device_status(wdev, &b); + } + ubus_send_reply(ctx, req, b.head); + return 0; +} + +static int +netifd_handle_wdev_get_validate(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct wireless_device *wdev; + int ret; + + wdev = get_wdev(msg, &ret); + if (ret == UBUS_STATUS_NOT_FOUND) + return ret; + + blob_buf_init(&b, 0); + if (wdev) { + wireless_device_get_validate(wdev, &b); + } else { + vlist_for_each_element(&wireless_devices, wdev, node) + wireless_device_get_validate(wdev, &b); + } + ubus_send_reply(ctx, req, b.head); + return 0; +} + +static int +netifd_handle_wdev_notify(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct wireless_device *wdev; + int ret; + + wdev = get_wdev(msg, &ret); + if (!wdev) + return ret; + + return wireless_device_notify(wdev, msg, req); +} + +static struct ubus_method wireless_object_methods[] = { + { .name = "up", .handler = netifd_handle_wdev_up }, + { .name = "down", .handler = netifd_handle_wdev_down }, + { .name = "status", .handler = netifd_handle_wdev_status }, + { .name = "notify", .handler = netifd_handle_wdev_notify }, + { .name = "get_validate", .handler = netifd_handle_wdev_get_validate }, +}; + +static struct ubus_object_type wireless_object_type = + UBUS_OBJECT_TYPE("netifd_iface", wireless_object_methods); + + +static struct ubus_object wireless_object = { + .name = "network.wireless", + .type = &wireless_object_type, + .methods = wireless_object_methods, + .n_methods = ARRAY_SIZE(wireless_object_methods), +}; + int netifd_ubus_init(const char *path) { uloop_init(); ubus_path = path; - ctx = ubus_connect(path); - if (!ctx) + ubus_ctx = ubus_connect(path); + if (!ubus_ctx) return -EIO; - DPRINTF("connected as %08x\n", ctx->local_id); - ctx->connection_lost = netifd_ubus_connection_lost; + DPRINTF("connected as %08x\n", ubus_ctx->local_id); + ubus_ctx->connection_lost = netifd_ubus_connection_lost; netifd_ubus_add_fd(); netifd_add_object(&main_object); netifd_add_object(&dev_object); + netifd_add_object(&wireless_object); netifd_add_iface_object(); return 0; @@ -984,7 +1185,7 @@ netifd_ubus_init(const char *path) void netifd_ubus_done(void) { - ubus_free(ctx); + ubus_free(ubus_ctx); } void @@ -993,7 +1194,18 @@ netifd_ubus_interface_event(struct interface *iface, bool up) blob_buf_init(&b, 0); blobmsg_add_string(&b, "action", up ? "ifup" : "ifdown"); blobmsg_add_string(&b, "interface", iface->name); - ubus_send_event(ctx, "network.interface", b.head); + ubus_send_event(ubus_ctx, "network.interface", b.head); +} + +void +netifd_ubus_interface_notify(struct interface *iface, bool up) +{ + const char *event = (up) ? "interface.update" : "interface.down"; + blob_buf_init(&b, 0); + blobmsg_add_string(&b, "interface", iface->name); + netifd_dump_status(iface); + ubus_notify(ubus_ctx, &iface_object, event, b.head, -1); + ubus_notify(ubus_ctx, &iface->ubus, event, b.head, -1); } void @@ -1009,7 +1221,7 @@ netifd_ubus_add_interface(struct interface *iface) obj->type = &iface_object_type; obj->methods = iface_object_methods; obj->n_methods = ARRAY_SIZE(iface_object_methods); - if (ubus_add_object(ctx, &iface->ubus)) { + if (ubus_add_object(ubus_ctx, &iface->ubus)) { DPRINTF("failed to publish ubus object for interface '%s'\n", iface->name); free(name); obj->name = NULL; @@ -1022,6 +1234,6 @@ netifd_ubus_remove_interface(struct interface *iface) if (!iface->ubus.name) return; - ubus_remove_object(ctx, &iface->ubus); + ubus_remove_object(ubus_ctx, &iface->ubus); free((void *) iface->ubus.name); }