device: extend device settings flags to 64 bit
[project/netifd.git] / ubus.c
1 /*
2 * netifd - network interface daemon
3 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14 #define _GNU_SOURCE
15
16 #include <arpa/inet.h>
17 #include <string.h>
18 #include <stdio.h>
19
20 #include "netifd.h"
21 #include "interface.h"
22 #include "proto.h"
23 #include "ubus.h"
24 #include "system.h"
25 #include "wireless.h"
26
27 struct ubus_context *ubus_ctx = NULL;
28 static struct blob_buf b;
29 static const char *ubus_path;
30
31 /* global object */
32
33 static int
34 netifd_handle_restart(struct ubus_context *ctx, struct ubus_object *obj,
35 struct ubus_request_data *req, const char *method,
36 struct blob_attr *msg)
37 {
38 netifd_restart();
39 return 0;
40 }
41
42 static int
43 netifd_handle_reload(struct ubus_context *ctx, struct ubus_object *obj,
44 struct ubus_request_data *req, const char *method,
45 struct blob_attr *msg)
46 {
47 if (netifd_reload())
48 return UBUS_STATUS_NOT_FOUND;
49
50 return UBUS_STATUS_OK;
51 }
52
53 enum {
54 HR_TARGET,
55 HR_V6,
56 HR_INTERFACE,
57 __HR_MAX
58 };
59
60 static const struct blobmsg_policy route_policy[__HR_MAX] = {
61 [HR_TARGET] = { .name = "target", .type = BLOBMSG_TYPE_STRING },
62 [HR_V6] = { .name = "v6", .type = BLOBMSG_TYPE_BOOL },
63 [HR_INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_STRING },
64 };
65
66 static int
67 netifd_add_host_route(struct ubus_context *ctx, struct ubus_object *obj,
68 struct ubus_request_data *req, const char *method,
69 struct blob_attr *msg)
70 {
71 struct blob_attr *tb[__HR_MAX];
72 struct interface *iface = NULL;
73 union if_addr a;
74 bool v6 = false;
75
76 blobmsg_parse(route_policy, __HR_MAX, tb, blob_data(msg), blob_len(msg));
77 if (!tb[HR_TARGET])
78 return UBUS_STATUS_INVALID_ARGUMENT;
79
80 if (tb[HR_V6])
81 v6 = blobmsg_get_bool(tb[HR_V6]);
82
83 if (tb[HR_INTERFACE])
84 iface = vlist_find(&interfaces, blobmsg_data(tb[HR_INTERFACE]), iface, node);
85
86 memset(&a, 0, sizeof(a));
87 if (!inet_pton(v6 ? AF_INET6 : AF_INET, blobmsg_data(tb[HR_TARGET]), &a))
88 return UBUS_STATUS_INVALID_ARGUMENT;
89
90
91 iface = interface_ip_add_target_route(&a, v6, iface);
92 if (!iface)
93 return UBUS_STATUS_NOT_FOUND;
94
95 blob_buf_init(&b, 0);
96 blobmsg_add_string(&b, "interface", iface->name);
97 ubus_send_reply(ctx, req, b.head);
98
99 return 0;
100 }
101
102 static int
103 netifd_get_proto_handlers(struct ubus_context *ctx, struct ubus_object *obj,
104 struct ubus_request_data *req, const char *method,
105 struct blob_attr *msg)
106 {
107 blob_buf_init(&b, 0);
108 proto_dump_handlers(&b);
109 ubus_send_reply(ctx, req, b.head);
110
111 return 0;
112 }
113
114
115 enum {
116 DI_NAME,
117 __DI_MAX
118 };
119
120 static const struct blobmsg_policy dynamic_policy[__DI_MAX] = {
121 [DI_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
122 };
123
124 static int
125 netifd_add_dynamic(struct ubus_context *ctx, struct ubus_object *obj,
126 struct ubus_request_data *req, const char *method,
127 struct blob_attr *msg)
128 {
129 struct blob_attr *tb[__DI_MAX];
130 struct interface *iface;
131 struct blob_attr *config;
132
133 blobmsg_parse(dynamic_policy, __DI_MAX, tb, blob_data(msg), blob_len(msg));
134
135 if (!tb[DI_NAME])
136 return UBUS_STATUS_INVALID_ARGUMENT;
137
138 const char *name = blobmsg_get_string(tb[DI_NAME]);
139
140 iface = interface_alloc(name, msg, true);
141 if (!iface)
142 return UBUS_STATUS_UNKNOWN_ERROR;
143
144 config = blob_memdup(msg);
145 if (!config)
146 goto error;
147
148 if (!interface_add(iface, config))
149 goto error_free_config;
150
151 return UBUS_STATUS_OK;
152
153 error_free_config:
154 free(config);
155 error:
156 free(iface);
157 return UBUS_STATUS_UNKNOWN_ERROR;
158 }
159
160 enum {
161 NETNS_UPDOWN_JAIL,
162 NETNS_UPDOWN_PID,
163 NETNS_UPDOWN_START,
164 __NETNS_UPDOWN_MAX
165 };
166
167 static const struct blobmsg_policy netns_updown_policy[__NETNS_UPDOWN_MAX] = {
168 [NETNS_UPDOWN_JAIL] = { .name = "jail", .type = BLOBMSG_TYPE_STRING },
169 [NETNS_UPDOWN_PID] = { .name = "pid", .type = BLOBMSG_TYPE_INT32 },
170 [NETNS_UPDOWN_START] = { .name = "start", .type = BLOBMSG_TYPE_BOOL },
171 };
172
173 static int
174 netifd_netns_updown(struct ubus_context *ctx, struct ubus_object *obj,
175 struct ubus_request_data *req, const char *method,
176 struct blob_attr *msg)
177 {
178 struct blob_attr *tb[__NETNS_UPDOWN_MAX];
179 char *jail;
180 pid_t netns_pid;
181 bool start;
182
183 blobmsg_parse(netns_updown_policy, __NETNS_UPDOWN_MAX, tb, blob_data(msg), blob_len(msg));
184 if (!tb[NETNS_UPDOWN_JAIL] || !tb[NETNS_UPDOWN_PID])
185 return UBUS_STATUS_INVALID_ARGUMENT;
186
187 start = tb[NETNS_UPDOWN_START] && blobmsg_get_bool(tb[NETNS_UPDOWN_START]);
188 jail = blobmsg_get_string(tb[NETNS_UPDOWN_JAIL]);
189 netns_pid = blobmsg_get_u32(tb[NETNS_UPDOWN_PID]);
190
191 if (start)
192 interface_start_jail(jail, netns_pid);
193 else
194 interface_stop_jail(jail, netns_pid);
195
196 return UBUS_STATUS_OK;
197 }
198
199 static struct ubus_method main_object_methods[] = {
200 { .name = "restart", .handler = netifd_handle_restart },
201 { .name = "reload", .handler = netifd_handle_reload },
202 UBUS_METHOD("add_host_route", netifd_add_host_route, route_policy),
203 { .name = "get_proto_handlers", .handler = netifd_get_proto_handlers },
204 UBUS_METHOD("add_dynamic", netifd_add_dynamic, dynamic_policy),
205 UBUS_METHOD("netns_updown", netifd_netns_updown, netns_updown_policy),
206 };
207
208 static struct ubus_object_type main_object_type =
209 UBUS_OBJECT_TYPE("netifd", main_object_methods);
210
211 static struct ubus_object main_object = {
212 .name = "network",
213 .type = &main_object_type,
214 .methods = main_object_methods,
215 .n_methods = ARRAY_SIZE(main_object_methods),
216 };
217
218 enum {
219 DEV_NAME,
220 __DEV_MAX,
221 };
222
223 static const struct blobmsg_policy dev_policy[__DEV_MAX] = {
224 [DEV_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
225 };
226
227 static int
228 netifd_dev_status(struct ubus_context *ctx, struct ubus_object *obj,
229 struct ubus_request_data *req, const char *method,
230 struct blob_attr *msg)
231 {
232 struct device *dev = NULL;
233 struct blob_attr *tb[__DEV_MAX];
234
235 blobmsg_parse(dev_policy, __DEV_MAX, tb, blob_data(msg), blob_len(msg));
236
237 if (tb[DEV_NAME]) {
238 dev = device_find(blobmsg_data(tb[DEV_NAME]));
239 if (!dev)
240 return UBUS_STATUS_INVALID_ARGUMENT;
241 }
242
243 blob_buf_init(&b, 0);
244 device_dump_status(&b, dev);
245 ubus_send_reply(ctx, req, b.head);
246
247 return 0;
248 }
249
250 enum {
251 ALIAS_ATTR_ALIAS,
252 ALIAS_ATTR_DEV,
253 __ALIAS_ATTR_MAX,
254 };
255
256 static const struct blobmsg_policy alias_attrs[__ALIAS_ATTR_MAX] = {
257 [ALIAS_ATTR_ALIAS] = { "alias", BLOBMSG_TYPE_ARRAY },
258 [ALIAS_ATTR_DEV] = { "device", BLOBMSG_TYPE_STRING },
259 };
260
261 static int
262 netifd_handle_alias(struct ubus_context *ctx, struct ubus_object *obj,
263 struct ubus_request_data *req, const char *method,
264 struct blob_attr *msg)
265 {
266 struct device *dev = NULL;
267 struct blob_attr *tb[__ALIAS_ATTR_MAX];
268 struct blob_attr *cur;
269 int rem;
270
271 blobmsg_parse(alias_attrs, __ALIAS_ATTR_MAX, tb, blob_data(msg), blob_len(msg));
272
273 if (!tb[ALIAS_ATTR_ALIAS])
274 return UBUS_STATUS_INVALID_ARGUMENT;
275
276 if ((cur = tb[ALIAS_ATTR_DEV]) != NULL) {
277 dev = device_get(blobmsg_data(cur), true);
278 if (!dev)
279 return UBUS_STATUS_NOT_FOUND;
280 }
281
282 blobmsg_for_each_attr(cur, tb[ALIAS_ATTR_ALIAS], rem) {
283 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
284 goto error;
285
286 if (!blobmsg_check_attr(cur, false))
287 goto error;
288
289 alias_notify_device(blobmsg_data(cur), dev);
290 }
291 return 0;
292
293 error:
294 device_free_unused(dev);
295 return UBUS_STATUS_INVALID_ARGUMENT;
296 }
297
298 enum {
299 DEV_STATE_NAME,
300 DEV_STATE_DEFER,
301 DEV_STATE_AUTH_STATUS,
302 __DEV_STATE_MAX,
303 };
304
305 static const struct blobmsg_policy dev_state_policy[__DEV_STATE_MAX] = {
306 [DEV_STATE_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
307 [DEV_STATE_DEFER] = { .name = "defer", .type = BLOBMSG_TYPE_BOOL },
308 [DEV_STATE_AUTH_STATUS] = { .name = "auth_status", .type = BLOBMSG_TYPE_BOOL },
309 };
310
311 static int
312 netifd_handle_set_state(struct ubus_context *ctx, struct ubus_object *obj,
313 struct ubus_request_data *req, const char *method,
314 struct blob_attr *msg)
315 {
316 struct device *dev = NULL;
317 struct blob_attr *tb[__DEV_STATE_MAX];
318 struct blob_attr *cur;
319
320 blobmsg_parse(dev_state_policy, __DEV_STATE_MAX, tb, blob_data(msg), blob_len(msg));
321
322 cur = tb[DEV_STATE_NAME];
323 if (!cur)
324 return UBUS_STATUS_INVALID_ARGUMENT;
325
326 dev = device_find(blobmsg_data(cur));
327 if (!dev)
328 return UBUS_STATUS_NOT_FOUND;
329
330 cur = tb[DEV_STATE_DEFER];
331 if (cur)
332 device_set_deferred(dev, !!blobmsg_get_u8(cur));
333
334 cur = tb[DEV_STATE_AUTH_STATUS];
335 if (cur)
336 device_set_auth_status(dev, !!blobmsg_get_u8(cur));
337
338 return 0;
339 }
340
341 #ifdef DUMMY_MODE
342 enum {
343 DEV_HOTPLUG_ATTR_NAME,
344 DEV_HOTPLUG_ATTR_ADD,
345 __DEV_HOTPLUG_ATTR_MAX,
346 };
347
348 static const struct blobmsg_policy dev_hotplug_policy[__DEV_HOTPLUG_ATTR_MAX] = {
349 [DEV_HOTPLUG_ATTR_NAME] = { "name", BLOBMSG_TYPE_STRING },
350 [DEV_HOTPLUG_ATTR_ADD] = { "add", BLOBMSG_TYPE_BOOL },
351 };
352
353 static int
354 netifd_handle_dev_hotplug(struct ubus_context *ctx, struct ubus_object *obj,
355 struct ubus_request_data *req, const char *method,
356 struct blob_attr *msg)
357 {
358 struct blob_attr *tb[__DEV_HOTPLUG_ATTR_MAX];
359 const char *name;
360
361 blobmsg_parse(dev_hotplug_policy, __DEV_HOTPLUG_ATTR_MAX, tb,
362 blob_data(msg), blob_len(msg));
363
364 if (!tb[DEV_HOTPLUG_ATTR_NAME] || !tb[DEV_HOTPLUG_ATTR_ADD])
365 return UBUS_STATUS_INVALID_ARGUMENT;
366
367 name = blobmsg_get_string(tb[DEV_HOTPLUG_ATTR_NAME]);
368 device_hotplug_event(name, blobmsg_get_bool(tb[DEV_HOTPLUG_ATTR_ADD]));
369
370 return 0;
371 }
372 #endif
373
374 static struct ubus_method dev_object_methods[] = {
375 UBUS_METHOD("status", netifd_dev_status, dev_policy),
376 UBUS_METHOD("set_alias", netifd_handle_alias, alias_attrs),
377 UBUS_METHOD("set_state", netifd_handle_set_state, dev_state_policy),
378 #ifdef DUMMY_MODE
379 UBUS_METHOD("hotplug_event", netifd_handle_dev_hotplug, dev_hotplug_policy),
380 #endif
381 };
382
383 static struct ubus_object_type dev_object_type =
384 UBUS_OBJECT_TYPE("device", dev_object_methods);
385
386 static struct ubus_object dev_object = {
387 .name = "network.device",
388 .type = &dev_object_type,
389 .methods = dev_object_methods,
390 .n_methods = ARRAY_SIZE(dev_object_methods),
391 };
392
393 static void
394 netifd_ubus_add_fd(void)
395 {
396 ubus_add_uloop(ubus_ctx);
397 system_fd_set_cloexec(ubus_ctx->sock.fd);
398 }
399
400 static void
401 netifd_ubus_reconnect_timer(struct uloop_timeout *timeout)
402 {
403 static struct uloop_timeout retry = {
404 .cb = netifd_ubus_reconnect_timer,
405 };
406 int t = 2;
407
408 if (ubus_reconnect(ubus_ctx, ubus_path) != 0) {
409 DPRINTF("failed to reconnect, trying again in %d seconds\n", t);
410 uloop_timeout_set(&retry, t * 1000);
411 return;
412 }
413
414 DPRINTF("reconnected to ubus, new id: %08x\n", ubus_ctx->local_id);
415 netifd_ubus_add_fd();
416 }
417
418 static void
419 netifd_ubus_connection_lost(struct ubus_context *ctx)
420 {
421 netifd_ubus_reconnect_timer(NULL);
422 }
423
424 /* per-interface object */
425
426 static int
427 netifd_handle_up(struct ubus_context *ctx, struct ubus_object *obj,
428 struct ubus_request_data *req, const char *method,
429 struct blob_attr *msg)
430 {
431 struct interface *iface;
432
433 iface = container_of(obj, struct interface, ubus);
434 interface_set_up(iface);
435
436 return 0;
437 }
438
439 static int
440 netifd_handle_down(struct ubus_context *ctx, struct ubus_object *obj,
441 struct ubus_request_data *req, const char *method,
442 struct blob_attr *msg)
443 {
444 struct interface *iface;
445
446 iface = container_of(obj, struct interface, ubus);
447 interface_set_down(iface);
448
449 return 0;
450 }
451
452 static int
453 netifd_handle_renew(struct ubus_context *ctx, struct ubus_object *obj,
454 struct ubus_request_data *req, const char *method,
455 struct blob_attr *msg)
456 {
457 struct interface *iface;
458
459 iface = container_of(obj, struct interface, ubus);
460 interface_renew(iface);
461
462 return 0;
463 }
464
465 static void
466 netifd_add_interface_errors(struct blob_buf *b, struct interface *iface)
467 {
468 struct interface_error *error;
469 void *e, *e2, *e3;
470 int i;
471
472 e = blobmsg_open_array(b, "errors");
473 list_for_each_entry(error, &iface->errors, list) {
474 e2 = blobmsg_open_table(b, NULL);
475
476 blobmsg_add_string(b, "subsystem", error->subsystem);
477 blobmsg_add_string(b, "code", error->code);
478 if (error->data[0]) {
479 e3 = blobmsg_open_array(b, "data");
480 for (i = 0; error->data[i]; i++)
481 blobmsg_add_string(b, NULL, error->data[i]);
482 blobmsg_close_array(b, e3);
483 }
484
485 blobmsg_close_table(b, e2);
486 }
487 blobmsg_close_array(b, e);
488 }
489
490 static void
491 interface_ip_dump_address_list(struct interface_ip_settings *ip, bool v6, bool enabled)
492 {
493 struct device_addr *addr;
494 char *buf;
495 void *a;
496 int buflen = 128;
497 int af;
498
499 time_t now = system_get_rtime();
500 vlist_for_each_element(&ip->addr, addr, node) {
501 if (addr->enabled != enabled)
502 continue;
503
504 if ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4)
505 af = AF_INET;
506 else
507 af = AF_INET6;
508
509 if (af != (v6 ? AF_INET6 : AF_INET))
510 continue;
511
512 a = blobmsg_open_table(&b, NULL);
513
514 buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
515 inet_ntop(af, &addr->addr, buf, buflen);
516 blobmsg_add_string_buffer(&b);
517
518 blobmsg_add_u32(&b, "mask", addr->mask);
519
520 if (addr->point_to_point) {
521 buf = blobmsg_alloc_string_buffer(&b, "ptpaddress", buflen);
522 inet_ntop(af, &addr->point_to_point, buf, buflen);
523 blobmsg_add_string_buffer(&b);
524 }
525
526 if (addr->preferred_until) {
527 int preferred = addr->preferred_until - now;
528 if (preferred < 0)
529 preferred = 0;
530 blobmsg_add_u32(&b, "preferred", preferred);
531 }
532
533 if (addr->valid_until)
534 blobmsg_add_u32(&b, "valid", addr->valid_until - now);
535
536 if (addr->pclass)
537 blobmsg_add_string(&b, "class", addr->pclass);
538
539 blobmsg_close_table(&b, a);
540 }
541 }
542
543 static void
544 interface_ip_dump_neighbor_list(struct interface_ip_settings *ip, bool enabled)
545 {
546 struct device_neighbor *neighbor;
547 int buflen = 128;
548 char *buf;
549 void *r;
550 int af;
551
552 vlist_for_each_element(&ip->neighbor, neighbor, node) {
553 if (neighbor->enabled != enabled)
554 continue;
555
556 if ((neighbor->flags & DEVADDR_FAMILY) == DEVADDR_INET4)
557 af = AF_INET;
558 else
559 af = AF_INET6;
560
561 r = blobmsg_open_table(&b, NULL);
562
563 if (neighbor->flags & DEVNEIGH_MAC)
564 blobmsg_add_string(&b, "mac", format_macaddr(neighbor->macaddr));
565
566 buf = blobmsg_alloc_string_buffer(&b , "address", buflen);
567 inet_ntop(af, &neighbor->addr, buf, buflen);
568 blobmsg_add_string_buffer(&b);
569
570 if (neighbor->proxy)
571 blobmsg_add_u32(&b, "proxy", neighbor->proxy);
572
573 if (neighbor->router)
574 blobmsg_add_u32(&b, "router", neighbor->router);
575
576 blobmsg_close_table(&b, r);
577 }
578 }
579
580 static void
581 interface_ip_dump_route_list(struct interface_ip_settings *ip, bool enabled)
582 {
583 struct device_route *route;
584 int buflen = 128;
585 char *buf;
586 void *r;
587 int af;
588
589 time_t now = system_get_rtime();
590 vlist_for_each_element(&ip->route, route, node) {
591 if (route->enabled != enabled)
592 continue;
593
594 if ((ip->no_defaultroute == enabled) && !route->mask)
595 continue;
596
597 if ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4)
598 af = AF_INET;
599 else
600 af = AF_INET6;
601
602 r = blobmsg_open_table(&b, NULL);
603
604 buf = blobmsg_alloc_string_buffer(&b, "target", buflen);
605 inet_ntop(af, &route->addr, buf, buflen);
606 blobmsg_add_string_buffer(&b);
607
608 blobmsg_add_u32(&b, "mask", route->mask);
609
610 buf = blobmsg_alloc_string_buffer(&b, "nexthop", buflen);
611 inet_ntop(af, &route->nexthop, buf, buflen);
612 blobmsg_add_string_buffer(&b);
613
614 if (route->flags & DEVROUTE_TYPE)
615 blobmsg_add_u32(&b, "type", route->type);
616
617 if (route->flags & DEVROUTE_PROTO)
618 blobmsg_add_u32(&b, "proto", route->proto);
619
620 if (route->flags & DEVROUTE_MTU)
621 blobmsg_add_u32(&b, "mtu", route->mtu);
622
623 if (route->flags & DEVROUTE_METRIC)
624 blobmsg_add_u32(&b, "metric", route->metric);
625
626 if (route->flags & DEVROUTE_TABLE)
627 blobmsg_add_u32(&b, "table", route->table);
628
629 if (route->valid_until)
630 blobmsg_add_u32(&b, "valid", route->valid_until - now);
631
632 buf = blobmsg_alloc_string_buffer(&b, "source", buflen);
633 inet_ntop(af, &route->source, buf, buflen);
634 snprintf(buf + strlen(buf), buflen - strlen(buf), "/%u", route->sourcemask);
635 blobmsg_add_string_buffer(&b);
636
637 blobmsg_close_table(&b, r);
638 }
639 }
640
641
642 static void
643 interface_ip_dump_prefix_list(struct interface_ip_settings *ip)
644 {
645 struct device_prefix *prefix;
646 char *buf;
647 void *a, *c;
648 const int buflen = INET6_ADDRSTRLEN;
649
650 time_t now = system_get_rtime();
651 vlist_for_each_element(&ip->prefix, prefix, node) {
652 a = blobmsg_open_table(&b, NULL);
653
654 buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
655 inet_ntop(AF_INET6, &prefix->addr, buf, buflen);
656 blobmsg_add_string_buffer(&b);
657
658 blobmsg_add_u32(&b, "mask", prefix->length);
659
660 if (prefix->preferred_until) {
661 int preferred = prefix->preferred_until - now;
662 if (preferred < 0)
663 preferred = 0;
664 blobmsg_add_u32(&b, "preferred", preferred);
665 }
666
667 if (prefix->valid_until)
668 blobmsg_add_u32(&b, "valid", prefix->valid_until - now);
669
670 blobmsg_add_string(&b, "class", prefix->pclass);
671
672 c = blobmsg_open_table(&b, "assigned");
673 struct device_prefix_assignment *assign;
674 list_for_each_entry(assign, &prefix->assignments, head) {
675 if (!assign->name[0])
676 continue;
677
678 struct in6_addr addr = prefix->addr;
679 addr.s6_addr32[1] |= htonl(assign->assigned);
680
681 void *d = blobmsg_open_table(&b, assign->name);
682
683 buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
684 inet_ntop(AF_INET6, &addr, buf, buflen);
685 blobmsg_add_string_buffer(&b);
686
687 blobmsg_add_u32(&b, "mask", assign->length);
688
689 blobmsg_close_table(&b, d);
690 }
691 blobmsg_close_table(&b, c);
692
693 blobmsg_close_table(&b, a);
694 }
695 }
696
697
698 static void
699 interface_ip_dump_prefix_assignment_list(struct interface *iface)
700 {
701 void *a;
702 char *buf;
703 const int buflen = INET6_ADDRSTRLEN;
704 time_t now = system_get_rtime();
705
706 struct device_prefix *prefix;
707 list_for_each_entry(prefix, &prefixes, head) {
708 struct device_prefix_assignment *assign;
709 list_for_each_entry(assign, &prefix->assignments, head) {
710 if (strcmp(assign->name, iface->name))
711 continue;
712
713 struct in6_addr addr = prefix->addr;
714 addr.s6_addr32[1] |= htonl(assign->assigned);
715
716 a = blobmsg_open_table(&b, NULL);
717
718 buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
719 inet_ntop(AF_INET6, &addr, buf, buflen);
720 blobmsg_add_string_buffer(&b);
721
722 blobmsg_add_u32(&b, "mask", assign->length);
723
724 if (prefix->preferred_until) {
725 int preferred = prefix->preferred_until - now;
726 if (preferred < 0)
727 preferred = 0;
728 blobmsg_add_u32(&b, "preferred", preferred);
729 }
730
731 if (prefix->valid_until)
732 blobmsg_add_u32(&b, "valid", prefix->valid_until - now);
733
734 void *c = blobmsg_open_table(&b, "local-address");
735 if (assign->enabled) {
736 buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
737 inet_ntop(AF_INET6, &assign->addr, buf, buflen);
738 blobmsg_add_string_buffer(&b);
739
740 blobmsg_add_u32(&b, "mask", assign->length);
741 }
742 blobmsg_close_table(&b, c);
743
744 blobmsg_close_table(&b, a);
745 }
746 }
747 }
748
749 static void
750 interface_ip_dump_dns_server_list(struct interface_ip_settings *ip, bool enabled)
751 {
752 struct dns_server *dns;
753 int buflen = 128;
754 char *buf;
755
756 vlist_simple_for_each_element(&ip->dns_servers, dns, node) {
757 if (ip->no_dns == enabled)
758 continue;
759
760 buf = blobmsg_alloc_string_buffer(&b, NULL, buflen);
761 inet_ntop(dns->af, &dns->addr, buf, buflen);
762 blobmsg_add_string_buffer(&b);
763 }
764 }
765
766 static void
767 interface_ip_dump_dns_search_list(struct interface_ip_settings *ip, bool enabled)
768 {
769 struct dns_search_domain *dns;
770
771 vlist_simple_for_each_element(&ip->dns_search, dns, node) {
772 if (ip->no_dns == enabled)
773 continue;
774
775 blobmsg_add_string(&b, NULL, dns->name);
776 }
777 }
778
779 static void
780 netifd_dump_status(struct interface *iface)
781 {
782 struct interface_data *data;
783 struct device *dev;
784 void *a, *inactive;
785
786 blobmsg_add_u8(&b, "up", iface->state == IFS_UP);
787 blobmsg_add_u8(&b, "pending", iface->state == IFS_SETUP);
788 blobmsg_add_u8(&b, "available", iface->available);
789 blobmsg_add_u8(&b, "autostart", iface->autostart);
790 blobmsg_add_u8(&b, "dynamic", iface->dynamic);
791
792 if (iface->state == IFS_UP) {
793 time_t cur = system_get_rtime();
794 blobmsg_add_u32(&b, "uptime", cur - iface->start_time);
795 if (iface->l3_dev.dev)
796 blobmsg_add_string(&b, "l3_device", iface->l3_dev.dev->ifname);
797 }
798
799 if (iface->proto_handler)
800 blobmsg_add_string(&b, "proto", iface->proto_handler->name);
801
802 dev = iface->main_dev.dev;
803 if (dev && !dev->hidden && iface->proto_handler &&
804 !(iface->proto_handler->flags & PROTO_FLAG_NODEV))
805 blobmsg_add_string(&b, "device", dev->ifname);
806
807 if (iface->jail)
808 blobmsg_add_string(&b, "jail", iface->jail);
809
810 if (iface->jail_ifname)
811 blobmsg_add_string(&b, "jail_ifname", iface->jail_ifname);
812
813 if (iface->state == IFS_UP) {
814 if (iface->updated) {
815 a = blobmsg_open_array(&b, "updated");
816
817 if (iface->updated & IUF_ADDRESS)
818 blobmsg_add_string(&b, NULL, "addresses");
819 if (iface->updated & IUF_ROUTE)
820 blobmsg_add_string(&b, NULL, "routes");
821 if (iface->updated & IUF_PREFIX)
822 blobmsg_add_string(&b, NULL, "prefixes");
823 if (iface->updated & IUF_DATA)
824 blobmsg_add_string(&b, NULL, "data");
825
826 blobmsg_close_array(&b, a);
827 }
828
829 if (iface->ip4table)
830 blobmsg_add_u32(&b, "ip4table", iface->ip4table);
831 if (iface->ip6table)
832 blobmsg_add_u32(&b, "ip6table", iface->ip6table);
833 blobmsg_add_u32(&b, "metric", iface->metric);
834 blobmsg_add_u32(&b, "dns_metric", iface->dns_metric);
835 blobmsg_add_u8(&b, "delegation", !iface->proto_ip.no_delegation);
836 if (iface->assignment_weight)
837 blobmsg_add_u32(&b, "ip6weight", iface->assignment_weight);
838 a = blobmsg_open_array(&b, "ipv4-address");
839 interface_ip_dump_address_list(&iface->config_ip, false, true);
840 interface_ip_dump_address_list(&iface->proto_ip, false, true);
841 blobmsg_close_array(&b, a);
842 a = blobmsg_open_array(&b, "ipv6-address");
843 interface_ip_dump_address_list(&iface->config_ip, true, true);
844 interface_ip_dump_address_list(&iface->proto_ip, true, true);
845 blobmsg_close_array(&b, a);
846 a = blobmsg_open_array(&b, "ipv6-prefix");
847 interface_ip_dump_prefix_list(&iface->config_ip);
848 interface_ip_dump_prefix_list(&iface->proto_ip);
849 blobmsg_close_array(&b, a);
850 a = blobmsg_open_array(&b, "ipv6-prefix-assignment");
851 interface_ip_dump_prefix_assignment_list(iface);
852 blobmsg_close_array(&b, a);
853 a = blobmsg_open_array(&b, "route");
854 interface_ip_dump_route_list(&iface->config_ip, true);
855 interface_ip_dump_route_list(&iface->proto_ip, true);
856 blobmsg_close_array(&b, a);
857 a = blobmsg_open_array(&b, "dns-server");
858 interface_ip_dump_dns_server_list(&iface->config_ip, true);
859 interface_ip_dump_dns_server_list(&iface->proto_ip, true);
860 blobmsg_close_array(&b, a);
861 a = blobmsg_open_array(&b, "dns-search");
862 interface_ip_dump_dns_search_list(&iface->config_ip, true);
863 interface_ip_dump_dns_search_list(&iface->proto_ip, true);
864 blobmsg_close_array(&b, a);
865 a = blobmsg_open_array(&b, "neighbors");
866 interface_ip_dump_neighbor_list(&iface->config_ip, true);
867 interface_ip_dump_neighbor_list(&iface->proto_ip, true);
868 blobmsg_close_array(&b, a);
869
870 inactive = blobmsg_open_table(&b, "inactive");
871 a = blobmsg_open_array(&b, "ipv4-address");
872 interface_ip_dump_address_list(&iface->config_ip, false, false);
873 interface_ip_dump_address_list(&iface->proto_ip, false, false);
874 blobmsg_close_array(&b, a);
875 a = blobmsg_open_array(&b, "ipv6-address");
876 interface_ip_dump_address_list(&iface->config_ip, true, false);
877 interface_ip_dump_address_list(&iface->proto_ip, true, false);
878 blobmsg_close_array(&b, a);
879 a = blobmsg_open_array(&b, "route");
880 interface_ip_dump_route_list(&iface->config_ip, false);
881 interface_ip_dump_route_list(&iface->proto_ip, false);
882 blobmsg_close_array(&b, a);
883 a = blobmsg_open_array(&b, "dns-server");
884 interface_ip_dump_dns_server_list(&iface->config_ip, false);
885 interface_ip_dump_dns_server_list(&iface->proto_ip, false);
886 blobmsg_close_array(&b, a);
887 a = blobmsg_open_array(&b, "dns-search");
888 interface_ip_dump_dns_search_list(&iface->config_ip, false);
889 interface_ip_dump_dns_search_list(&iface->proto_ip, false);
890 blobmsg_close_array(&b, a);
891 a = blobmsg_open_array(&b, "neighbors");
892 interface_ip_dump_neighbor_list(&iface->config_ip, false);
893 interface_ip_dump_neighbor_list(&iface->proto_ip, false);
894 blobmsg_close_array(&b, a);
895 blobmsg_close_table(&b, inactive);
896 }
897
898 a = blobmsg_open_table(&b, "data");
899 avl_for_each_element(&iface->data, data, node)
900 blobmsg_add_blob(&b, data->data);
901
902 blobmsg_close_table(&b, a);
903
904 if (!list_empty(&iface->errors))
905 netifd_add_interface_errors(&b, iface);
906 }
907
908 static int
909 netifd_handle_status(struct ubus_context *ctx, struct ubus_object *obj,
910 struct ubus_request_data *req, const char *method,
911 struct blob_attr *msg)
912 {
913 struct interface *iface = container_of(obj, struct interface, ubus);
914
915 blob_buf_init(&b, 0);
916 netifd_dump_status(iface);
917 ubus_send_reply(ctx, req, b.head);
918
919 return 0;
920 }
921
922
923 static int
924 netifd_handle_dump(struct ubus_context *ctx, struct ubus_object *obj,
925 struct ubus_request_data *req, const char *method,
926 struct blob_attr *msg)
927 {
928 blob_buf_init(&b, 0);
929 void *a = blobmsg_open_array(&b, "interface");
930
931 struct interface *iface;
932 vlist_for_each_element(&interfaces, iface, node) {
933 void *i = blobmsg_open_table(&b, NULL);
934 blobmsg_add_string(&b, "interface", iface->name);
935 netifd_dump_status(iface);
936 blobmsg_close_table(&b, i);
937 }
938
939 blobmsg_close_array(&b, a);
940 ubus_send_reply(ctx, req, b.head);
941
942 return 0;
943 }
944
945 enum {
946 DEV_LINK_NAME,
947 DEV_LINK_EXT,
948 DEV_LINK_VLAN,
949 __DEV_LINK_MAX,
950 };
951
952 static const struct blobmsg_policy dev_link_policy[__DEV_LINK_MAX] = {
953 [DEV_LINK_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
954 [DEV_LINK_EXT] = { .name = "link-ext", .type = BLOBMSG_TYPE_BOOL },
955 [DEV_LINK_VLAN] = { .name = "vlan", .type = BLOBMSG_TYPE_ARRAY },
956 };
957
958 static int
959 netifd_iface_handle_device(struct ubus_context *ctx, struct ubus_object *obj,
960 struct ubus_request_data *req, const char *method,
961 struct blob_attr *msg)
962 {
963 struct blob_attr *tb[__DEV_LINK_MAX];
964 struct blob_attr *cur;
965 struct interface *iface;
966 bool add = !strncmp(method, "add", 3);
967 bool link_ext = true;
968
969 iface = container_of(obj, struct interface, ubus);
970
971 blobmsg_parse(dev_link_policy, __DEV_LINK_MAX, tb, blob_data(msg), blob_len(msg));
972
973 if (!tb[DEV_LINK_NAME])
974 return UBUS_STATUS_INVALID_ARGUMENT;
975
976 cur = tb[DEV_LINK_EXT];
977 if (cur)
978 link_ext = blobmsg_get_bool(cur);
979
980 return interface_handle_link(iface, blobmsg_data(tb[DEV_LINK_NAME]),
981 tb[DEV_LINK_VLAN], add, link_ext);
982 }
983
984
985 static int
986 netifd_iface_notify_proto(struct ubus_context *ctx, struct ubus_object *obj,
987 struct ubus_request_data *req, const char *method,
988 struct blob_attr *msg)
989 {
990 struct interface *iface;
991
992 iface = container_of(obj, struct interface, ubus);
993
994 if (!iface->proto || !iface->proto->notify)
995 return UBUS_STATUS_NOT_SUPPORTED;
996
997 return iface->proto->notify(iface->proto, msg);
998 }
999
1000 static void
1001 netifd_iface_do_remove(struct uloop_timeout *timeout)
1002 {
1003 struct interface *iface;
1004
1005 iface = container_of(timeout, struct interface, remove_timer);
1006 vlist_delete(&interfaces, &iface->node);
1007 }
1008
1009 static int
1010 netifd_iface_remove(struct ubus_context *ctx, struct ubus_object *obj,
1011 struct ubus_request_data *req, const char *method,
1012 struct blob_attr *msg)
1013 {
1014 struct interface *iface;
1015
1016 iface = container_of(obj, struct interface, ubus);
1017 if (iface->remove_timer.cb)
1018 return UBUS_STATUS_INVALID_ARGUMENT;
1019
1020 iface->remove_timer.cb = netifd_iface_do_remove;
1021 uloop_timeout_set(&iface->remove_timer, 100);
1022 return 0;
1023 }
1024
1025 static int
1026 netifd_handle_iface_prepare(struct ubus_context *ctx, struct ubus_object *obj,
1027 struct ubus_request_data *req, const char *method,
1028 struct blob_attr *msg)
1029 {
1030 struct interface *iface;
1031 struct device *dev, *bridge_dev = NULL;
1032 const struct device_hotplug_ops *ops;
1033
1034 iface = container_of(obj, struct interface, ubus);
1035 dev = iface->main_dev.dev;
1036 if (!dev)
1037 goto out;
1038
1039 ops = dev->hotplug_ops;
1040 if (!ops)
1041 goto out;
1042
1043 ops->prepare(dev, &bridge_dev);
1044
1045 out:
1046 blob_buf_init(&b, 0);
1047 if (bridge_dev)
1048 blobmsg_add_string(&b, "bridge", bridge_dev->ifname);
1049 ubus_send_reply(ctx, req, b.head);
1050
1051 return 0;
1052 }
1053
1054 static int
1055 netifd_handle_set_data(struct ubus_context *ctx, struct ubus_object *obj,
1056 struct ubus_request_data *req, const char *method,
1057 struct blob_attr *msg)
1058 {
1059 struct interface *iface;
1060
1061 iface = container_of(obj, struct interface, ubus);
1062
1063 return interface_parse_data(iface, msg);
1064 }
1065
1066 static struct ubus_method iface_object_methods[] = {
1067 { .name = "up", .handler = netifd_handle_up },
1068 { .name = "down", .handler = netifd_handle_down },
1069 { .name = "renew", .handler = netifd_handle_renew },
1070 { .name = "status", .handler = netifd_handle_status },
1071 { .name = "prepare", .handler = netifd_handle_iface_prepare },
1072 { .name = "dump", .handler = netifd_handle_dump },
1073 UBUS_METHOD("add_device", netifd_iface_handle_device, dev_link_policy ),
1074 UBUS_METHOD("remove_device", netifd_iface_handle_device, dev_link_policy ),
1075 { .name = "notify_proto", .handler = netifd_iface_notify_proto },
1076 { .name = "remove", .handler = netifd_iface_remove },
1077 { .name = "set_data", .handler = netifd_handle_set_data },
1078 };
1079
1080 static struct ubus_object_type iface_object_type =
1081 UBUS_OBJECT_TYPE("netifd_iface", iface_object_methods);
1082
1083
1084 static struct ubus_object iface_object = {
1085 .name = "network.interface",
1086 .type = &iface_object_type,
1087 .n_methods = ARRAY_SIZE(iface_object_methods),
1088 };
1089
1090 static void netifd_add_object(struct ubus_object *obj)
1091 {
1092 int ret = ubus_add_object(ubus_ctx, obj);
1093
1094 if (ret != 0)
1095 fprintf(stderr, "Failed to publish object '%s': %s\n", obj->name, ubus_strerror(ret));
1096 }
1097
1098 static const struct blobmsg_policy iface_policy = {
1099 .name = "interface",
1100 .type = BLOBMSG_TYPE_STRING,
1101 };
1102
1103 static int
1104 netifd_handle_iface(struct ubus_context *ctx, struct ubus_object *obj,
1105 struct ubus_request_data *req, const char *method,
1106 struct blob_attr *msg)
1107 {
1108 struct interface *iface;
1109 struct blob_attr *tb;
1110 int i;
1111
1112 blobmsg_parse(&iface_policy, 1, &tb, blob_data(msg), blob_len(msg));
1113 if (!tb)
1114 return UBUS_STATUS_INVALID_ARGUMENT;
1115
1116 iface = vlist_find(&interfaces, blobmsg_data(tb), iface, node);
1117 if (!iface)
1118 return UBUS_STATUS_NOT_FOUND;
1119
1120 for (i = 0; i < ARRAY_SIZE(iface_object_methods); i++) {
1121 ubus_handler_t cb;
1122
1123 if (strcmp(method, iface_object_methods[i].name) != 0)
1124 continue;
1125
1126 cb = iface_object_methods[i].handler;
1127 return cb(ctx, &iface->ubus, req, method, msg);
1128 }
1129
1130 return UBUS_STATUS_INVALID_ARGUMENT;
1131 }
1132
1133 static void netifd_add_iface_object(void)
1134 {
1135 struct ubus_method *methods;
1136 int i;
1137
1138 methods = calloc(1, sizeof(iface_object_methods));
1139 if (!methods)
1140 return;
1141
1142 memcpy(methods, iface_object_methods, sizeof(iface_object_methods));
1143 iface_object.methods = methods;
1144
1145 for (i = 0; i < ARRAY_SIZE(iface_object_methods); i++) {
1146 if (methods[i].handler == netifd_handle_dump)
1147 continue;
1148
1149 methods[i].handler = netifd_handle_iface;
1150 methods[i].policy = &iface_policy;
1151 methods[i].n_policy = 1;
1152 }
1153 netifd_add_object(&iface_object);
1154 }
1155
1156 static struct wireless_device *
1157 get_wdev(struct blob_attr *msg, int *ret)
1158 {
1159 struct blobmsg_policy wdev_policy = {
1160 .name = "device",
1161 .type = BLOBMSG_TYPE_STRING,
1162 };
1163 struct blob_attr *dev_attr;
1164 struct wireless_device *wdev = NULL;
1165
1166
1167 blobmsg_parse(&wdev_policy, 1, &dev_attr, blob_data(msg), blob_len(msg));
1168 if (!dev_attr) {
1169 *ret = UBUS_STATUS_INVALID_ARGUMENT;
1170 return NULL;
1171 }
1172
1173 wdev = vlist_find(&wireless_devices, blobmsg_data(dev_attr), wdev, node);
1174 if (!wdev) {
1175 *ret = UBUS_STATUS_NOT_FOUND;
1176 return NULL;
1177 }
1178
1179 *ret = 0;
1180 return wdev;
1181 }
1182
1183 static int
1184 netifd_handle_wdev_reconf(struct ubus_context *ctx, struct ubus_object *obj,
1185 struct ubus_request_data *req, const char *method,
1186 struct blob_attr *msg)
1187 {
1188 struct wireless_device *wdev;
1189 int ret;
1190
1191 wdev = get_wdev(msg, &ret);
1192 if (ret == UBUS_STATUS_NOT_FOUND)
1193 return ret;
1194
1195 if (wdev) {
1196 wireless_device_reconf(wdev);
1197 } else {
1198 vlist_for_each_element(&wireless_devices, wdev, node)
1199 wireless_device_reconf(wdev);
1200 }
1201
1202 return 0;
1203 }
1204
1205 static int
1206 netifd_handle_wdev_up(struct ubus_context *ctx, struct ubus_object *obj,
1207 struct ubus_request_data *req, const char *method,
1208 struct blob_attr *msg)
1209 {
1210 struct wireless_device *wdev;
1211 int ret;
1212
1213 wdev = get_wdev(msg, &ret);
1214 if (ret == UBUS_STATUS_NOT_FOUND)
1215 return ret;
1216
1217 if (wdev) {
1218 wireless_device_set_up(wdev);
1219 } else {
1220 vlist_for_each_element(&wireless_devices, wdev, node)
1221 wireless_device_set_up(wdev);
1222 }
1223
1224 return 0;
1225 }
1226
1227 static int
1228 netifd_handle_wdev_down(struct ubus_context *ctx, struct ubus_object *obj,
1229 struct ubus_request_data *req, const char *method,
1230 struct blob_attr *msg)
1231 {
1232 struct wireless_device *wdev;
1233 int ret;
1234
1235 wdev = get_wdev(msg, &ret);
1236 if (ret == UBUS_STATUS_NOT_FOUND)
1237 return ret;
1238
1239 if (wdev) {
1240 wireless_device_set_down(wdev);
1241 } else {
1242 vlist_for_each_element(&wireless_devices, wdev, node)
1243 wireless_device_set_down(wdev);
1244 }
1245
1246 return 0;
1247 }
1248
1249 static int
1250 netifd_handle_wdev_status(struct ubus_context *ctx, struct ubus_object *obj,
1251 struct ubus_request_data *req, const char *method,
1252 struct blob_attr *msg)
1253 {
1254 struct wireless_device *wdev;
1255 int ret;
1256
1257 wdev = get_wdev(msg, &ret);
1258 if (ret == UBUS_STATUS_NOT_FOUND)
1259 return ret;
1260
1261 blob_buf_init(&b, 0);
1262 if (wdev) {
1263 wireless_device_status(wdev, &b);
1264 } else {
1265 vlist_for_each_element(&wireless_devices, wdev, node)
1266 wireless_device_status(wdev, &b);
1267 }
1268 ubus_send_reply(ctx, req, b.head);
1269 return 0;
1270 }
1271
1272 static int
1273 netifd_handle_wdev_get_validate(struct ubus_context *ctx, struct ubus_object *obj,
1274 struct ubus_request_data *req, const char *method,
1275 struct blob_attr *msg)
1276 {
1277 struct wireless_device *wdev;
1278 int ret;
1279
1280 wdev = get_wdev(msg, &ret);
1281 if (ret == UBUS_STATUS_NOT_FOUND)
1282 return ret;
1283
1284 blob_buf_init(&b, 0);
1285 if (wdev) {
1286 wireless_device_get_validate(wdev, &b);
1287 } else {
1288 vlist_for_each_element(&wireless_devices, wdev, node)
1289 wireless_device_get_validate(wdev, &b);
1290 }
1291 ubus_send_reply(ctx, req, b.head);
1292 return 0;
1293 }
1294
1295 static int
1296 netifd_handle_wdev_notify(struct ubus_context *ctx, struct ubus_object *obj,
1297 struct ubus_request_data *req, const char *method,
1298 struct blob_attr *msg)
1299 {
1300 struct wireless_device *wdev;
1301 int ret;
1302
1303 wdev = get_wdev(msg, &ret);
1304 if (!wdev)
1305 return ret;
1306
1307 return wireless_device_notify(wdev, msg, req);
1308 }
1309
1310 static struct ubus_method wireless_object_methods[] = {
1311 { .name = "up", .handler = netifd_handle_wdev_up },
1312 { .name = "down", .handler = netifd_handle_wdev_down },
1313 { .name = "reconf", .handler = netifd_handle_wdev_reconf },
1314 { .name = "status", .handler = netifd_handle_wdev_status },
1315 { .name = "notify", .handler = netifd_handle_wdev_notify },
1316 { .name = "get_validate", .handler = netifd_handle_wdev_get_validate },
1317 };
1318
1319 static struct ubus_object_type wireless_object_type =
1320 UBUS_OBJECT_TYPE("netifd_iface", wireless_object_methods);
1321
1322
1323 static struct ubus_object wireless_object = {
1324 .name = "network.wireless",
1325 .type = &wireless_object_type,
1326 .methods = wireless_object_methods,
1327 .n_methods = ARRAY_SIZE(wireless_object_methods),
1328 };
1329
1330 int
1331 netifd_extdev_invoke(uint32_t id, const char *method, struct blob_attr *msg,
1332 ubus_data_handler_t data_cb, void *data)
1333 {
1334 return ubus_invoke(ubus_ctx, id, method, msg, data_cb, data, 3000);
1335 }
1336
1337 int
1338 netifd_ubus_init(const char *path)
1339 {
1340 uloop_init();
1341 ubus_path = path;
1342
1343 ubus_ctx = ubus_connect(path);
1344 if (!ubus_ctx)
1345 return -EIO;
1346
1347 DPRINTF("connected as %08x\n", ubus_ctx->local_id);
1348 ubus_ctx->connection_lost = netifd_ubus_connection_lost;
1349 netifd_ubus_add_fd();
1350
1351 netifd_add_object(&main_object);
1352 netifd_add_object(&dev_object);
1353 netifd_add_object(&wireless_object);
1354 netifd_add_iface_object();
1355
1356 return 0;
1357 }
1358
1359 void
1360 netifd_ubus_done(void)
1361 {
1362 ubus_free(ubus_ctx);
1363 }
1364
1365 void
1366 netifd_ubus_interface_event(struct interface *iface, bool up)
1367 {
1368 blob_buf_init(&b, 0);
1369 blobmsg_add_string(&b, "action", up ? "ifup" : "ifdown");
1370 blobmsg_add_string(&b, "interface", iface->name);
1371 ubus_send_event(ubus_ctx, "network.interface", b.head);
1372 }
1373
1374 void
1375 netifd_ubus_interface_notify(struct interface *iface, bool up)
1376 {
1377 const char *event = (up) ? "interface.update" : "interface.down";
1378 blob_buf_init(&b, 0);
1379 blobmsg_add_string(&b, "interface", iface->name);
1380 netifd_dump_status(iface);
1381 ubus_notify(ubus_ctx, &iface_object, event, b.head, -1);
1382 ubus_notify(ubus_ctx, &iface->ubus, event, b.head, -1);
1383 }
1384
1385 void
1386 netifd_ubus_add_interface(struct interface *iface)
1387 {
1388 struct ubus_object *obj = &iface->ubus;
1389 char *name = NULL;
1390
1391 if (asprintf(&name, "%s.interface.%s", main_object.name, iface->name) == -1)
1392 return;
1393
1394 obj->name = name;
1395 obj->type = &iface_object_type;
1396 obj->methods = iface_object_methods;
1397 obj->n_methods = ARRAY_SIZE(iface_object_methods);
1398 if (ubus_add_object(ubus_ctx, &iface->ubus)) {
1399 DPRINTF("failed to publish ubus object for interface '%s'\n", iface->name);
1400 free(name);
1401 obj->name = NULL;
1402 }
1403 }
1404
1405 void
1406 netifd_ubus_remove_interface(struct interface *iface)
1407 {
1408 if (!iface->ubus.name)
1409 return;
1410
1411 ubus_remove_object(ubus_ctx, &iface->ubus);
1412 free((void *) iface->ubus.name);
1413 }