12 static struct ubus_context *ctx = NULL;
13 static struct blob_buf b;
18 netifd_handle_restart(struct ubus_context *ctx, struct ubus_object *obj,
19 struct ubus_request_data *req, const char *method,
20 struct blob_attr *msg)
27 netifd_handle_reload(struct ubus_context *ctx, struct ubus_object *obj,
28 struct ubus_request_data *req, const char *method,
29 struct blob_attr *msg)
35 static struct ubus_method main_object_methods[] = {
36 { .name = "restart", .handler = netifd_handle_restart },
37 { .name = "reload", .handler = netifd_handle_reload },
40 static struct ubus_object_type main_object_type =
41 UBUS_OBJECT_TYPE("netifd", main_object_methods);
43 static struct ubus_object main_object = {
45 .type = &main_object_type,
46 .methods = main_object_methods,
47 .n_methods = ARRAY_SIZE(main_object_methods),
55 static const struct blobmsg_policy dev_policy[__DEV_MAX] = {
56 [DEV_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
60 netifd_dev_status(struct ubus_context *ctx, struct ubus_object *obj,
61 struct ubus_request_data *req, const char *method,
62 struct blob_attr *msg)
64 struct device *dev = NULL;
65 struct blob_attr *tb[__DEV_MAX];
67 blobmsg_parse(dev_policy, __DEV_MAX, tb, blob_data(msg), blob_len(msg));
70 dev = device_get(blobmsg_data(tb[DEV_NAME]), false);
72 return UBUS_STATUS_INVALID_ARGUMENT;
76 device_dump_status(&b, dev);
77 ubus_send_reply(ctx, req, b.head);
82 static struct ubus_method dev_object_methods[] = {
83 UBUS_METHOD("status", netifd_dev_status, dev_policy)
86 static struct ubus_object_type dev_object_type =
87 UBUS_OBJECT_TYPE("device", dev_object_methods);
89 static struct ubus_object dev_object = {
90 .name = "network.device",
91 .type = &dev_object_type,
92 .methods = dev_object_methods,
93 .n_methods = ARRAY_SIZE(dev_object_methods),
97 netifd_ubus_init(const char *path)
101 ctx = ubus_connect(path);
105 DPRINTF("connected as %08x\n", ctx->local_id);
109 ret = ubus_add_object(ctx, &main_object);
113 ret = ubus_add_object(ctx, &dev_object);
117 fprintf(stderr, "Failed to publish object: %s\n", ubus_strerror(ret));
122 netifd_ubus_done(void)
128 /* per-interface object */
131 netifd_handle_up(struct ubus_context *ctx, struct ubus_object *obj,
132 struct ubus_request_data *req, const char *method,
133 struct blob_attr *msg)
135 struct interface *iface;
137 iface = container_of(obj, struct interface, ubus);
138 interface_set_up(iface);
144 netifd_handle_down(struct ubus_context *ctx, struct ubus_object *obj,
145 struct ubus_request_data *req, const char *method,
146 struct blob_attr *msg)
148 struct interface *iface;
150 iface = container_of(obj, struct interface, ubus);
151 interface_set_down(iface);
157 netifd_add_interface_errors(struct blob_buf *b, struct interface *iface)
159 struct interface_error *error;
163 e = blobmsg_open_array(b, "errors");
164 list_for_each_entry(error, &iface->errors, list) {
165 e2 = blobmsg_open_table(b, NULL);
167 blobmsg_add_string(b, "subsystem", error->subsystem);
168 blobmsg_add_string(b, "code", error->code);
169 if (error->data[0]) {
170 e3 = blobmsg_open_array(b, "data");
171 for (i = 0; error->data[i]; i++)
172 blobmsg_add_string(b, NULL, error->data[i]);
173 blobmsg_close_array(b, e3);
176 blobmsg_close_table(b, e2);
178 blobmsg_close_array(b, e);
182 netifd_handle_status(struct ubus_context *ctx, struct ubus_object *obj,
183 struct ubus_request_data *req, const char *method,
184 struct blob_attr *msg)
186 struct interface *iface;
188 iface = container_of(obj, struct interface, ubus);
190 blob_buf_init(&b, 0);
191 blobmsg_add_u8(&b, "up", iface->state == IFS_UP);
192 blobmsg_add_u8(&b, "pending", iface->state == IFS_SETUP);
193 blobmsg_add_u8(&b, "available", iface->available);
194 blobmsg_add_u8(&b, "autostart", iface->autostart);
196 if (iface->state == IFS_UP) {
197 time_t cur = system_get_rtime();
198 blobmsg_add_u32(&b, "uptime", cur - iface->start_time);
201 if (iface->main_dev.dev) {
202 struct device *dev = iface->main_dev.dev;
206 /* use a different field for virtual devices */
212 devinfo = blobmsg_open_table(&b, field);
213 blobmsg_add_string(&b, "name", dev->ifname);
215 blobmsg_close_table(&b, devinfo);
218 if (!list_is_empty(&iface->errors))
219 netifd_add_interface_errors(&b, iface);
221 ubus_send_reply(ctx, req, b.head);
227 netifd_iface_handle_device(struct ubus_context *ctx, struct ubus_object *obj,
228 struct ubus_request_data *req, const char *method,
229 struct blob_attr *msg)
231 struct interface *iface;
232 struct device *dev, *main_dev;
233 struct blob_attr *tb[__DEV_MAX];
234 bool add = !strncmp(method, "add", 3);
237 iface = container_of(obj, struct interface, ubus);
239 blobmsg_parse(dev_policy, __DEV_MAX, tb, blob_data(msg), blob_len(msg));
242 return UBUS_STATUS_INVALID_ARGUMENT;
244 main_dev = iface->main_dev.dev;
246 return UBUS_STATUS_NOT_FOUND;
248 if (!main_dev->hotplug_ops)
249 return UBUS_STATUS_NOT_SUPPORTED;
251 dev = device_get(blobmsg_data(tb[DEV_NAME]), add);
253 return UBUS_STATUS_NOT_FOUND;
255 if (main_dev != dev) {
257 ret = main_dev->hotplug_ops->add(main_dev, dev);
259 ret = main_dev->hotplug_ops->del(main_dev, dev);
261 ret = UBUS_STATUS_UNKNOWN_ERROR;
263 ret = UBUS_STATUS_INVALID_ARGUMENT;
267 device_free_unused(dev);
274 netifd_iface_notify_proto(struct ubus_context *ctx, struct ubus_object *obj,
275 struct ubus_request_data *req, const char *method,
276 struct blob_attr *msg)
278 struct interface *iface;
280 iface = container_of(obj, struct interface, ubus);
282 if (!iface->proto || !iface->proto->notify)
283 return UBUS_STATUS_NOT_SUPPORTED;
285 return iface->proto->notify(iface->proto, msg);
289 netifd_iface_do_remove(struct uloop_timeout *timeout)
291 struct interface *iface;
293 iface = container_of(timeout, struct interface, remove_timer);
294 vlist_delete(&interfaces, &iface->node);
298 netifd_iface_remove(struct ubus_context *ctx, struct ubus_object *obj,
299 struct ubus_request_data *req, const char *method,
300 struct blob_attr *msg)
302 struct interface *iface;
304 iface = container_of(obj, struct interface, ubus);
305 if (iface->remove_timer.cb)
306 return UBUS_STATUS_INVALID_ARGUMENT;
308 iface->remove_timer.cb = netifd_iface_do_remove;
309 uloop_timeout_set(&iface->remove_timer, 100);
313 static struct ubus_method iface_object_methods[] = {
314 { .name = "up", .handler = netifd_handle_up },
315 { .name = "down", .handler = netifd_handle_down },
316 { .name = "status", .handler = netifd_handle_status },
317 { .name = "add_device", .handler = netifd_iface_handle_device,
318 .policy = dev_policy, .n_policy = __DEV_MAX },
319 { .name = "remove_device", .handler = netifd_iface_handle_device,
320 .policy = dev_policy, .n_policy = __DEV_MAX },
321 { .name = "notify_proto", .handler = netifd_iface_notify_proto },
322 { .name = "remove", .handler = netifd_iface_remove }
325 static struct ubus_object_type iface_object_type =
326 UBUS_OBJECT_TYPE("netifd_iface", iface_object_methods);
330 netifd_ubus_interface_event(struct interface *iface, bool up)
332 blob_buf_init(&b, 0);
333 blobmsg_add_string(&b, "action", up ? "ifup" : "ifdown");
334 blobmsg_add_string(&b, "interface", iface->name);
335 ubus_send_event(ctx, "network.interface", b.head);
339 netifd_ubus_add_interface(struct interface *iface)
341 struct ubus_object *obj = &iface->ubus;
344 asprintf(&name, "%s.interface.%s", main_object.name, iface->name);
349 obj->type = &iface_object_type;
350 obj->methods = iface_object_methods;
351 obj->n_methods = ARRAY_SIZE(iface_object_methods);
352 if (ubus_add_object(ctx, &iface->ubus)) {
353 DPRINTF("failed to publish ubus object for interface '%s'\n", iface->name);
360 netifd_ubus_remove_interface(struct interface *iface)
362 if (!iface->ubus.name)
365 ubus_remove_object(ctx, &iface->ubus);
366 free((void *) iface->ubus.name);