• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/netifd/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();
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 int
375 netifd_handle_stp_init(struct ubus_context *ctx, struct ubus_object *obj,
376                        struct ubus_request_data *req, const char *method,
377                        struct blob_attr *msg)
378 {
379         device_stp_init();
380 
381         return 0;
382 }
383 
384 static struct ubus_method dev_object_methods[] = {
385         UBUS_METHOD("status", netifd_dev_status, dev_policy),
386         UBUS_METHOD("set_alias", netifd_handle_alias, alias_attrs),
387         UBUS_METHOD("set_state", netifd_handle_set_state, dev_state_policy),
388 #ifdef DUMMY_MODE
389         UBUS_METHOD("hotplug_event", netifd_handle_dev_hotplug, dev_hotplug_policy),
390 #endif
391         UBUS_METHOD_NOARG("stp_init", netifd_handle_stp_init)
392 };
393 
394 static struct ubus_object_type dev_object_type =
395         UBUS_OBJECT_TYPE("device", dev_object_methods);
396 
397 static struct ubus_object dev_object = {
398         .name = "network.device",
399         .type = &dev_object_type,
400         .methods = dev_object_methods,
401         .n_methods = ARRAY_SIZE(dev_object_methods),
402 };
403 
404 static void
405 netifd_ubus_add_fd(void)
406 {
407         ubus_add_uloop(ubus_ctx);
408         system_fd_set_cloexec(ubus_ctx->sock.fd);
409 }
410 
411 void netifd_ubus_device_notify(const char *event, struct blob_attr *data, int timeout)
412 {
413         ubus_notify(ubus_ctx, &dev_object, event, data, timeout);
414 }
415 
416 static void
417 netifd_ubus_reconnect_timer(struct uloop_timeout *timeout)
418 {
419         static struct uloop_timeout retry = {
420                 .cb = netifd_ubus_reconnect_timer,
421         };
422         int t = 2;
423 
424         if (ubus_reconnect(ubus_ctx, ubus_path) != 0) {
425                 DPRINTF("failed to reconnect, trying again in %d seconds\n", t);
426                 uloop_timeout_set(&retry, t * 1000);
427                 return;
428         }
429 
430         DPRINTF("reconnected to ubus, new id: %08x\n", ubus_ctx->local_id);
431         netifd_ubus_add_fd();
432 }
433 
434 static void
435 netifd_ubus_connection_lost(struct ubus_context *ctx)
436 {
437         netifd_ubus_reconnect_timer(NULL);
438 }
439 
440 /* per-interface object */
441 
442 static int
443 netifd_handle_up(struct ubus_context *ctx, struct ubus_object *obj,
444                  struct ubus_request_data *req, const char *method,
445                  struct blob_attr *msg)
446 {
447         struct interface *iface;
448 
449         iface = container_of(obj, struct interface, ubus);
450         interface_set_up(iface);
451 
452         return 0;
453 }
454 
455 static int
456 netifd_handle_down(struct ubus_context *ctx, struct ubus_object *obj,
457                    struct ubus_request_data *req, const char *method,
458                    struct blob_attr *msg)
459 {
460         struct interface *iface;
461 
462         iface = container_of(obj, struct interface, ubus);
463         interface_set_down(iface);
464 
465         return 0;
466 }
467 
468 static int
469 netifd_handle_renew(struct ubus_context *ctx, struct ubus_object *obj,
470                    struct ubus_request_data *req, const char *method,
471                    struct blob_attr *msg)
472 {
473         struct interface *iface;
474 
475         iface = container_of(obj, struct interface, ubus);
476         interface_renew(iface);
477 
478         return 0;
479 }
480 
481 static void
482 netifd_add_interface_errors(struct blob_buf *b, struct interface *iface)
483 {
484         struct interface_error *error;
485         void *e, *e2, *e3;
486         int i;
487 
488         e = blobmsg_open_array(b, "errors");
489         list_for_each_entry(error, &iface->errors, list) {
490                 e2 = blobmsg_open_table(b, NULL);
491 
492                 blobmsg_add_string(b, "subsystem", error->subsystem);
493                 blobmsg_add_string(b, "code", error->code);
494                 if (error->data[0]) {
495                         e3 = blobmsg_open_array(b, "data");
496                         for (i = 0; error->data[i]; i++)
497                                 blobmsg_add_string(b, NULL, error->data[i]);
498                         blobmsg_close_array(b, e3);
499                 }
500 
501                 blobmsg_close_table(b, e2);
502         }
503         blobmsg_close_array(b, e);
504 }
505 
506 static void
507 interface_ip_dump_address_list(struct interface_ip_settings *ip, bool v6, bool enabled)
508 {
509         struct device_addr *addr;
510         char *buf;
511         void *a;
512         int buflen = 128;
513         int af;
514 
515         time_t now = system_get_rtime();
516         vlist_for_each_element(&ip->addr, addr, node) {
517                 if (addr->enabled != enabled)
518                         continue;
519 
520                 if ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4)
521                         af = AF_INET;
522                 else
523                         af = AF_INET6;
524 
525                 if (af != (v6 ? AF_INET6 : AF_INET))
526                         continue;
527 
528                 a = blobmsg_open_table(&b, NULL);
529 
530                 buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
531                 inet_ntop(af, &addr->addr, buf, buflen);
532                 blobmsg_add_string_buffer(&b);
533 
534                 blobmsg_add_u32(&b, "mask", addr->mask);
535 
536                 if (addr->point_to_point) {
537                         buf = blobmsg_alloc_string_buffer(&b, "ptpaddress", buflen);
538                         inet_ntop(af, &addr->point_to_point, buf, buflen);
539                         blobmsg_add_string_buffer(&b);
540                 }
541 
542                 if (addr->preferred_until) {
543                         int preferred = addr->preferred_until - now;
544                         if (preferred < 0)
545                                 preferred = 0;
546                         blobmsg_add_u32(&b, "preferred", preferred);
547                 }
548 
549                 if (addr->valid_until)
550                         blobmsg_add_u32(&b, "valid", addr->valid_until - now);
551 
552                 if (addr->pclass)
553                         blobmsg_add_string(&b, "class", addr->pclass);
554 
555                 blobmsg_close_table(&b, a);
556         }
557 }
558 
559 static void
560 interface_ip_dump_neighbor_list(struct interface_ip_settings *ip, bool enabled)
561 {
562         struct device_neighbor *neighbor;
563         int buflen = 128;
564         char *buf;
565         void *r;
566         int af;
567 
568         vlist_for_each_element(&ip->neighbor, neighbor, node) {
569                 if (neighbor->enabled != enabled)
570                         continue;
571 
572                 if ((neighbor->flags & DEVADDR_FAMILY) == DEVADDR_INET4)
573                         af = AF_INET;
574                 else
575                         af = AF_INET6;
576 
577                 r = blobmsg_open_table(&b, NULL);
578 
579                 if (neighbor->flags & DEVNEIGH_MAC)
580                         blobmsg_add_string(&b, "mac", format_macaddr(neighbor->macaddr));
581 
582                 buf = blobmsg_alloc_string_buffer(&b , "address", buflen);
583                 inet_ntop(af, &neighbor->addr, buf, buflen);
584                 blobmsg_add_string_buffer(&b);
585 
586                 if (neighbor->proxy)
587                         blobmsg_add_u32(&b, "proxy", neighbor->proxy);
588 
589                 if (neighbor->router)
590                         blobmsg_add_u32(&b, "router", neighbor->router);
591 
592                 blobmsg_close_table(&b, r);
593         }
594 }
595 
596 static void
597 interface_ip_dump_route_list(struct interface_ip_settings *ip, bool enabled)
598 {
599         struct device_route *route;
600         int buflen = 128;
601         char *buf;
602         void *r;
603         int af;
604 
605         time_t now = system_get_rtime();
606         vlist_for_each_element(&ip->route, route, node) {
607                 if (route->enabled != enabled)
608                         continue;
609 
610                 if ((ip->no_defaultroute == enabled) && !route->mask)
611                         continue;
612 
613                 if ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4)
614                         af = AF_INET;
615                 else
616                         af = AF_INET6;
617 
618                 r = blobmsg_open_table(&b, NULL);
619 
620                 buf = blobmsg_alloc_string_buffer(&b, "target", buflen);
621                 inet_ntop(af, &route->addr, buf, buflen);
622                 blobmsg_add_string_buffer(&b);
623 
624                 blobmsg_add_u32(&b, "mask", route->mask);
625 
626                 buf = blobmsg_alloc_string_buffer(&b, "nexthop", buflen);
627                 inet_ntop(af, &route->nexthop, buf, buflen);
628                 blobmsg_add_string_buffer(&b);
629 
630                 if (route->flags & DEVROUTE_TYPE)
631                         blobmsg_add_u32(&b, "type", route->type);
632 
633                 if (route->flags & DEVROUTE_PROTO)
634                         blobmsg_add_u32(&b, "proto", route->proto);
635 
636                 if (route->flags & DEVROUTE_MTU)
637                         blobmsg_add_u32(&b, "mtu", route->mtu);
638 
639                 if (route->flags & DEVROUTE_METRIC)
640                         blobmsg_add_u32(&b, "metric", route->metric);
641 
642                 if (route->flags & DEVROUTE_TABLE)
643                         blobmsg_add_u32(&b, "table", route->table);
644 
645                 if (route->valid_until)
646                         blobmsg_add_u32(&b, "valid", route->valid_until - now);
647 
648                 buf = blobmsg_alloc_string_buffer(&b, "source", buflen);
649                 inet_ntop(af, &route->source, buf, buflen);
650                 snprintf(buf + strlen(buf), buflen - strlen(buf), "/%u", route->sourcemask);
651                 blobmsg_add_string_buffer(&b);
652 
653                 blobmsg_close_table(&b, r);
654         }
655 }
656 
657 
658 static void
659 interface_ip_dump_prefix_list(struct interface_ip_settings *ip)
660 {
661         struct device_prefix *prefix;
662         char *buf;
663         void *a, *c;
664         const int buflen = INET6_ADDRSTRLEN;
665 
666         time_t now = system_get_rtime();
667         vlist_for_each_element(&ip->prefix, prefix, node) {
668                 a = blobmsg_open_table(&b, NULL);
669 
670                 buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
671                 inet_ntop(AF_INET6, &prefix->addr, buf, buflen);
672                 blobmsg_add_string_buffer(&b);
673 
674                 blobmsg_add_u32(&b, "mask", prefix->length);
675 
676                 if (prefix->preferred_until) {
677                         int preferred = prefix->preferred_until - now;
678                         if (preferred < 0)
679                                 preferred = 0;
680                         blobmsg_add_u32(&b, "preferred", preferred);
681                 }
682 
683                 if (prefix->valid_until)
684                         blobmsg_add_u32(&b, "valid", prefix->valid_until - now);
685 
686                 blobmsg_add_string(&b, "class", prefix->pclass);
687 
688                 c = blobmsg_open_table(&b, "assigned");
689                 struct device_prefix_assignment *assign;
690                 list_for_each_entry(assign, &prefix->assignments, head) {
691                         if (!assign->name[0])
692                                 continue;
693 
694                         struct in6_addr addr = prefix->addr;
695                         addr.s6_addr32[1] |= htonl(assign->assigned);
696 
697                         void *d = blobmsg_open_table(&b, assign->name);
698 
699                         buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
700                         inet_ntop(AF_INET6, &addr, buf, buflen);
701                         blobmsg_add_string_buffer(&b);
702 
703                         blobmsg_add_u32(&b, "mask", assign->length);
704 
705                         blobmsg_close_table(&b, d);
706                 }
707                 blobmsg_close_table(&b, c);
708 
709                 blobmsg_close_table(&b, a);
710         }
711 }
712 
713 
714 static void
715 interface_ip_dump_prefix_assignment_list(struct interface *iface)
716 {
717         void *a;
718         char *buf;
719         const int buflen = INET6_ADDRSTRLEN;
720         time_t now = system_get_rtime();
721 
722         struct device_prefix *prefix;
723         list_for_each_entry(prefix, &prefixes, head) {
724                 struct device_prefix_assignment *assign;
725                 list_for_each_entry(assign, &prefix->assignments, head) {
726                         if (strcmp(assign->name, iface->name))
727                                 continue;
728 
729                         struct in6_addr addr = prefix->addr;
730                         addr.s6_addr32[1] |= htonl(assign->assigned);
731 
732                         a = blobmsg_open_table(&b, NULL);
733 
734                         buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
735                         inet_ntop(AF_INET6, &addr, buf, buflen);
736                         blobmsg_add_string_buffer(&b);
737 
738                         blobmsg_add_u32(&b, "mask", assign->length);
739 
740                         if (prefix->preferred_until) {
741                                 int preferred = prefix->preferred_until - now;
742                                 if (preferred < 0)
743                                         preferred = 0;
744                                 blobmsg_add_u32(&b, "preferred", preferred);
745                         }
746 
747                         if (prefix->valid_until)
748                                 blobmsg_add_u32(&b, "valid", prefix->valid_until - now);
749 
750                         void *c = blobmsg_open_table(&b, "local-address");
751                         if (assign->enabled) {
752                                 buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
753                                 inet_ntop(AF_INET6, &assign->addr, buf, buflen);
754                                 blobmsg_add_string_buffer(&b);
755 
756                                 blobmsg_add_u32(&b, "mask", assign->length);
757                         }
758                         blobmsg_close_table(&b, c);
759 
760                         blobmsg_close_table(&b, a);
761                 }
762         }
763 }
764 
765 static void
766 interface_ip_dump_dns_server_list(struct interface_ip_settings *ip, bool enabled)
767 {
768         struct dns_server *dns;
769         int buflen = 128;
770         char *buf;
771 
772         vlist_simple_for_each_element(&ip->dns_servers, dns, node) {
773                 if (ip->no_dns == enabled)
774                         continue;
775 
776                 buf = blobmsg_alloc_string_buffer(&b, NULL, buflen);
777                 inet_ntop(dns->af, &dns->addr, buf, buflen);
778                 blobmsg_add_string_buffer(&b);
779         }
780 }
781 
782 static void
783 interface_ip_dump_dns_search_list(struct interface_ip_settings *ip, bool enabled)
784 {
785         struct dns_search_domain *dns;
786 
787         vlist_simple_for_each_element(&ip->dns_search, dns, node) {
788                 if (ip->no_dns == enabled)
789                         continue;
790 
791                 blobmsg_add_string(&b, NULL, dns->name);
792         }
793 }
794 
795 static void
796 netifd_dump_status(struct interface *iface)
797 {
798         struct interface_data *data;
799         struct device *dev;
800         void *a, *inactive;
801 
802         blobmsg_add_u8(&b, "up", iface->state == IFS_UP);
803         blobmsg_add_u8(&b, "pending", iface->state == IFS_SETUP);
804         blobmsg_add_u8(&b, "available", iface->available);
805         blobmsg_add_u8(&b, "autostart", iface->autostart);
806         blobmsg_add_u8(&b, "dynamic", iface->dynamic);
807 
808         if (iface->state == IFS_UP) {
809                 time_t cur = system_get_rtime();
810                 blobmsg_add_u32(&b, "uptime", cur - iface->start_time);
811                 if (iface->l3_dev.dev)
812                         blobmsg_add_string(&b, "l3_device", iface->l3_dev.dev->ifname);
813         }
814 
815         if (iface->proto_handler)
816                 blobmsg_add_string(&b, "proto", iface->proto_handler->name);
817 
818         dev = iface->main_dev.dev;
819         if (dev && !dev->hidden && iface->proto_handler &&
820             !(iface->proto_handler->flags & PROTO_FLAG_NODEV))
821                 blobmsg_add_string(&b, "device", dev->ifname);
822 
823         if (iface->jail)
824                 blobmsg_add_string(&b, "jail", iface->jail);
825 
826         if (iface->jail_ifname)
827                 blobmsg_add_string(&b, "jail_ifname", iface->jail_ifname);
828 
829         if (iface->state == IFS_UP) {
830                 if (iface->updated) {
831                         a = blobmsg_open_array(&b, "updated");
832 
833                         if (iface->updated & IUF_ADDRESS)
834                                 blobmsg_add_string(&b, NULL, "addresses");
835                         if (iface->updated & IUF_ROUTE)
836                                 blobmsg_add_string(&b, NULL, "routes");
837                         if (iface->updated & IUF_PREFIX)
838                                 blobmsg_add_string(&b, NULL, "prefixes");
839                         if (iface->updated & IUF_DATA)
840                                 blobmsg_add_string(&b, NULL, "data");
841 
842                         blobmsg_close_array(&b, a);
843                 }
844 
845                 if (iface->ip4table)
846                         blobmsg_add_u32(&b, "ip4table", iface->ip4table);
847                 if (iface->ip6table)
848                         blobmsg_add_u32(&b, "ip6table", iface->ip6table);
849                 blobmsg_add_u32(&b, "metric", iface->metric);
850                 blobmsg_add_u32(&b, "dns_metric", iface->dns_metric);
851                 blobmsg_add_u8(&b, "delegation", !iface->proto_ip.no_delegation);
852                 if (iface->assignment_weight)
853                         blobmsg_add_u32(&b, "ip6weight", iface->assignment_weight);
854                 a = blobmsg_open_array(&b, "ipv4-address");
855                 interface_ip_dump_address_list(&iface->config_ip, false, true);
856                 interface_ip_dump_address_list(&iface->proto_ip, false, true);
857                 blobmsg_close_array(&b, a);
858                 a = blobmsg_open_array(&b, "ipv6-address");
859                 interface_ip_dump_address_list(&iface->config_ip, true, true);
860                 interface_ip_dump_address_list(&iface->proto_ip, true, true);
861                 blobmsg_close_array(&b, a);
862                 a = blobmsg_open_array(&b, "ipv6-prefix");
863                 interface_ip_dump_prefix_list(&iface->config_ip);
864                 interface_ip_dump_prefix_list(&iface->proto_ip);
865                 blobmsg_close_array(&b, a);
866                 a = blobmsg_open_array(&b, "ipv6-prefix-assignment");
867                 interface_ip_dump_prefix_assignment_list(iface);
868                 blobmsg_close_array(&b, a);
869                 a = blobmsg_open_array(&b, "route");
870                 interface_ip_dump_route_list(&iface->config_ip, true);
871                 interface_ip_dump_route_list(&iface->proto_ip, true);
872                 blobmsg_close_array(&b, a);
873                 a = blobmsg_open_array(&b, "dns-server");
874                 interface_ip_dump_dns_server_list(&iface->config_ip, true);
875                 interface_ip_dump_dns_server_list(&iface->proto_ip, true);
876                 blobmsg_close_array(&b, a);
877                 a = blobmsg_open_array(&b, "dns-search");
878                 interface_ip_dump_dns_search_list(&iface->config_ip, true);
879                 interface_ip_dump_dns_search_list(&iface->proto_ip, true);
880                 blobmsg_close_array(&b, a);
881                 a = blobmsg_open_array(&b, "neighbors");
882                 interface_ip_dump_neighbor_list(&iface->config_ip, true);
883                 interface_ip_dump_neighbor_list(&iface->proto_ip, true);
884                 blobmsg_close_array(&b, a);
885 
886                 inactive = blobmsg_open_table(&b, "inactive");
887                 a = blobmsg_open_array(&b, "ipv4-address");
888                 interface_ip_dump_address_list(&iface->config_ip, false, false);
889                 interface_ip_dump_address_list(&iface->proto_ip, false, false);
890                 blobmsg_close_array(&b, a);
891                 a = blobmsg_open_array(&b, "ipv6-address");
892                 interface_ip_dump_address_list(&iface->config_ip, true, false);
893                 interface_ip_dump_address_list(&iface->proto_ip, true, false);
894                 blobmsg_close_array(&b, a);
895                 a = blobmsg_open_array(&b, "route");
896                 interface_ip_dump_route_list(&iface->config_ip, false);
897                 interface_ip_dump_route_list(&iface->proto_ip, false);
898                 blobmsg_close_array(&b, a);
899                 a = blobmsg_open_array(&b, "dns-server");
900                 interface_ip_dump_dns_server_list(&iface->config_ip, false);
901                 interface_ip_dump_dns_server_list(&iface->proto_ip, false);
902                 blobmsg_close_array(&b, a);
903                 a = blobmsg_open_array(&b, "dns-search");
904                 interface_ip_dump_dns_search_list(&iface->config_ip, false);
905                 interface_ip_dump_dns_search_list(&iface->proto_ip, false);
906                 blobmsg_close_array(&b, a);
907                 a = blobmsg_open_array(&b, "neighbors");
908                 interface_ip_dump_neighbor_list(&iface->config_ip, false);
909                 interface_ip_dump_neighbor_list(&iface->proto_ip, false);
910                 blobmsg_close_array(&b, a);
911                 blobmsg_close_table(&b, inactive);
912         }
913 
914         a = blobmsg_open_table(&b, "data");
915         avl_for_each_element(&iface->data, data, node)
916                 blobmsg_add_blob(&b, data->data);
917 
918         blobmsg_close_table(&b, a);
919 
920         if (!list_empty(&iface->errors))
921                 netifd_add_interface_errors(&b, iface);
922 }
923 
924 static int
925 netifd_handle_status(struct ubus_context *ctx, struct ubus_object *obj,
926                      struct ubus_request_data *req, const char *method,
927                      struct blob_attr *msg)
928 {
929         struct interface *iface = container_of(obj, struct interface, ubus);
930 
931         blob_buf_init(&b, 0);
932         netifd_dump_status(iface);
933         ubus_send_reply(ctx, req, b.head);
934 
935         return 0;
936 }
937 
938 
939 static int
940 netifd_handle_dump(struct ubus_context *ctx, struct ubus_object *obj,
941                      struct ubus_request_data *req, const char *method,
942                      struct blob_attr *msg)
943 {
944         blob_buf_init(&b, 0);
945         void *a = blobmsg_open_array(&b, "interface");
946 
947         struct interface *iface;
948         vlist_for_each_element(&interfaces, iface, node) {
949                 void *i = blobmsg_open_table(&b, NULL);
950                 blobmsg_add_string(&b, "interface", iface->name);
951                 netifd_dump_status(iface);
952                 blobmsg_close_table(&b, i);
953         }
954 
955         blobmsg_close_array(&b, a);
956         ubus_send_reply(ctx, req, b.head);
957 
958         return 0;
959 }
960 
961 enum {
962         DEV_LINK_NAME,
963         DEV_LINK_EXT,
964         DEV_LINK_VLAN,
965         __DEV_LINK_MAX,
966 };
967 
968 static const struct blobmsg_policy dev_link_policy[__DEV_LINK_MAX] = {
969         [DEV_LINK_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
970         [DEV_LINK_EXT] = { .name = "link-ext", .type = BLOBMSG_TYPE_BOOL },
971         [DEV_LINK_VLAN] = { .name = "vlan", .type = BLOBMSG_TYPE_ARRAY },
972 };
973 
974 static int
975 netifd_iface_handle_device(struct ubus_context *ctx, struct ubus_object *obj,
976                            struct ubus_request_data *req, const char *method,
977                            struct blob_attr *msg)
978 {
979         struct blob_attr *tb[__DEV_LINK_MAX];
980         struct blob_attr *cur;
981         struct interface *iface;
982         bool add = !strncmp(method, "add", 3);
983         bool link_ext = true;
984 
985         iface = container_of(obj, struct interface, ubus);
986 
987         blobmsg_parse(dev_link_policy, __DEV_LINK_MAX, tb, blob_data(msg), blob_len(msg));
988 
989         if (!tb[DEV_LINK_NAME])
990                 return UBUS_STATUS_INVALID_ARGUMENT;
991 
992         cur = tb[DEV_LINK_EXT];
993         if (cur)
994                 link_ext = blobmsg_get_bool(cur);
995 
996         return interface_handle_link(iface, blobmsg_data(tb[DEV_LINK_NAME]),
997                                      tb[DEV_LINK_VLAN], add, link_ext);
998 }
999 
1000 
1001 static int
1002 netifd_iface_notify_proto(struct ubus_context *ctx, struct ubus_object *obj,
1003                           struct ubus_request_data *req, const char *method,
1004                           struct blob_attr *msg)
1005 {
1006         struct interface *iface;
1007 
1008         iface = container_of(obj, struct interface, ubus);
1009 
1010         if (!iface->proto || !iface->proto->notify)
1011                 return UBUS_STATUS_NOT_SUPPORTED;
1012 
1013         return iface->proto->notify(iface->proto, msg);
1014 }
1015 
1016 static void
1017 netifd_iface_do_remove(struct uloop_timeout *timeout)
1018 {
1019         struct interface *iface;
1020 
1021         iface = container_of(timeout, struct interface, remove_timer);
1022         vlist_delete(&interfaces, &iface->node);
1023 }
1024 
1025 static int
1026 netifd_iface_remove(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 
1032         iface = container_of(obj, struct interface, ubus);
1033         if (iface->remove_timer.cb)
1034                 return UBUS_STATUS_INVALID_ARGUMENT;
1035 
1036         iface->remove_timer.cb = netifd_iface_do_remove;
1037         uloop_timeout_set(&iface->remove_timer, 100);
1038         return 0;
1039 }
1040 
1041 static int
1042 netifd_handle_iface_prepare(struct ubus_context *ctx, struct ubus_object *obj,
1043                             struct ubus_request_data *req, const char *method,
1044                             struct blob_attr *msg)
1045 {
1046         struct interface *iface;
1047         struct device *dev, *bridge_dev = NULL;
1048         const struct device_hotplug_ops *ops;
1049 
1050         iface = container_of(obj, struct interface, ubus);
1051         dev = iface->main_dev.dev;
1052         if (!dev)
1053                 goto out;
1054 
1055         ops = dev->hotplug_ops;
1056         if (!ops)
1057                 goto out;
1058 
1059         ops->prepare(dev, &bridge_dev);
1060 
1061 out:
1062         blob_buf_init(&b, 0);
1063         if (bridge_dev)
1064                 blobmsg_add_string(&b, "bridge", bridge_dev->ifname);
1065         ubus_send_reply(ctx, req, b.head);
1066 
1067         return 0;
1068 }
1069 
1070 static int
1071 netifd_handle_set_data(struct ubus_context *ctx, struct ubus_object *obj,
1072                        struct ubus_request_data *req, const char *method,
1073                        struct blob_attr *msg)
1074 {
1075         struct interface *iface;
1076 
1077         iface = container_of(obj, struct interface, ubus);
1078 
1079         return interface_parse_data(iface, msg);
1080 }
1081 
1082 static struct ubus_method iface_object_methods[] = {
1083         { .name = "up", .handler = netifd_handle_up },
1084         { .name = "down", .handler = netifd_handle_down },
1085         { .name = "renew", .handler = netifd_handle_renew },
1086         { .name = "status", .handler = netifd_handle_status },
1087         { .name = "prepare", .handler = netifd_handle_iface_prepare },
1088         { .name = "dump", .handler = netifd_handle_dump },
1089         UBUS_METHOD("add_device", netifd_iface_handle_device, dev_link_policy ),
1090         UBUS_METHOD("remove_device", netifd_iface_handle_device, dev_link_policy ),
1091         { .name = "notify_proto", .handler = netifd_iface_notify_proto },
1092         { .name = "remove", .handler = netifd_iface_remove },
1093         { .name = "set_data", .handler = netifd_handle_set_data },
1094 };
1095 
1096 static struct ubus_object_type iface_object_type =
1097         UBUS_OBJECT_TYPE("netifd_iface", iface_object_methods);
1098 
1099 
1100 static struct ubus_object iface_object = {
1101         .name = "network.interface",
1102         .type = &iface_object_type,
1103         .n_methods = ARRAY_SIZE(iface_object_methods),
1104 };
1105 
1106 static void netifd_add_object(struct ubus_object *obj)
1107 {
1108         int ret = ubus_add_object(ubus_ctx, obj);
1109 
1110         if (ret != 0)
1111                 fprintf(stderr, "Failed to publish object '%s': %s\n", obj->name, ubus_strerror(ret));
1112 }
1113 
1114 static const struct blobmsg_policy iface_policy = {
1115         .name = "interface",
1116         .type = BLOBMSG_TYPE_STRING,
1117 };
1118 
1119 static int
1120 netifd_handle_iface(struct ubus_context *ctx, struct ubus_object *obj,
1121                     struct ubus_request_data *req, const char *method,
1122                     struct blob_attr *msg)
1123 {
1124         struct interface *iface;
1125         struct blob_attr *tb;
1126         int i;
1127 
1128         blobmsg_parse(&iface_policy, 1, &tb, blob_data(msg), blob_len(msg));
1129         if (!tb)
1130                 return UBUS_STATUS_INVALID_ARGUMENT;
1131 
1132         iface = vlist_find(&interfaces, blobmsg_data(tb), iface, node);
1133         if (!iface)
1134                 return UBUS_STATUS_NOT_FOUND;
1135 
1136         for (i = 0; i < ARRAY_SIZE(iface_object_methods); i++) {
1137                 ubus_handler_t cb;
1138 
1139                 if (strcmp(method, iface_object_methods[i].name) != 0)
1140                         continue;
1141 
1142                 cb = iface_object_methods[i].handler;
1143                 return cb(ctx, &iface->ubus, req, method, msg);
1144         }
1145 
1146         return UBUS_STATUS_INVALID_ARGUMENT;
1147 }
1148 
1149 static void netifd_add_iface_object(void)
1150 {
1151         struct ubus_method *methods;
1152         int i;
1153 
1154         methods = calloc(1, sizeof(iface_object_methods));
1155         if (!methods)
1156                 return;
1157 
1158         memcpy(methods, iface_object_methods, sizeof(iface_object_methods));
1159         iface_object.methods = methods;
1160 
1161         for (i = 0; i < ARRAY_SIZE(iface_object_methods); i++) {
1162                 if (methods[i].handler == netifd_handle_dump)
1163                         continue;
1164 
1165                 methods[i].handler = netifd_handle_iface;
1166                 methods[i].policy = &iface_policy;
1167                 methods[i].n_policy = 1;
1168         }
1169         netifd_add_object(&iface_object);
1170 }
1171 
1172 static struct wireless_device *
1173 get_wdev(struct blob_attr *msg, int *ret)
1174 {
1175         struct blobmsg_policy wdev_policy = {
1176                 .name = "device",
1177                 .type = BLOBMSG_TYPE_STRING,
1178         };
1179         struct blob_attr *dev_attr;
1180         struct wireless_device *wdev = NULL;
1181 
1182 
1183         blobmsg_parse(&wdev_policy, 1, &dev_attr, blob_data(msg), blob_len(msg));
1184         if (!dev_attr) {
1185                 *ret = UBUS_STATUS_INVALID_ARGUMENT;
1186                 return NULL;
1187         }
1188 
1189         wdev = vlist_find(&wireless_devices, blobmsg_data(dev_attr), wdev, node);
1190         if (!wdev) {
1191                 *ret = UBUS_STATUS_NOT_FOUND;
1192                 return NULL;
1193         }
1194 
1195         *ret = 0;
1196         return wdev;
1197 }
1198 
1199 static int
1200 netifd_handle_wdev_reconf(struct ubus_context *ctx, struct ubus_object *obj,
1201                           struct ubus_request_data *req, const char *method,
1202                           struct blob_attr *msg)
1203 {
1204         struct wireless_device *wdev;
1205         int ret;
1206 
1207         wdev = get_wdev(msg, &ret);
1208         if (ret == UBUS_STATUS_NOT_FOUND)
1209                 return ret;
1210 
1211         if (wdev) {
1212                 wireless_device_reconf(wdev);
1213         } else {
1214                 vlist_for_each_element(&wireless_devices, wdev, node)
1215                         wireless_device_reconf(wdev);
1216         }
1217 
1218         return 0;
1219 }
1220 
1221 static int
1222 netifd_handle_wdev_up(struct ubus_context *ctx, struct ubus_object *obj,
1223                       struct ubus_request_data *req, const char *method,
1224                       struct blob_attr *msg)
1225 {
1226         struct wireless_device *wdev;
1227         int ret;
1228 
1229         wdev = get_wdev(msg, &ret);
1230         if (ret == UBUS_STATUS_NOT_FOUND)
1231                 return ret;
1232 
1233         if (wdev) {
1234                 wireless_device_set_up(wdev);
1235         } else {
1236                 vlist_for_each_element(&wireless_devices, wdev, node)
1237                         wireless_device_set_up(wdev);
1238         }
1239 
1240         return 0;
1241 }
1242 
1243 static int
1244 netifd_handle_wdev_down(struct ubus_context *ctx, struct ubus_object *obj,
1245                         struct ubus_request_data *req, const char *method,
1246                         struct blob_attr *msg)
1247 {
1248         struct wireless_device *wdev;
1249         int ret;
1250 
1251         wdev = get_wdev(msg, &ret);
1252         if (ret == UBUS_STATUS_NOT_FOUND)
1253                 return ret;
1254 
1255         if (wdev) {
1256                 wireless_device_set_down(wdev);
1257         } else {
1258                 vlist_for_each_element(&wireless_devices, wdev, node)
1259                         wireless_device_set_down(wdev);
1260         }
1261 
1262         return 0;
1263 }
1264 
1265 static int
1266 netifd_handle_wdev_status(struct ubus_context *ctx, struct ubus_object *obj,
1267                           struct ubus_request_data *req, const char *method,
1268                           struct blob_attr *msg)
1269 {
1270         struct wireless_device *wdev;
1271         int ret;
1272 
1273         wdev = get_wdev(msg, &ret);
1274         if (ret == UBUS_STATUS_NOT_FOUND)
1275                 return ret;
1276 
1277         blob_buf_init(&b, 0);
1278         if (wdev) {
1279                 wireless_device_status(wdev, &b);
1280         } else {
1281                 vlist_for_each_element(&wireless_devices, wdev, node)
1282                         wireless_device_status(wdev, &b);
1283         }
1284         ubus_send_reply(ctx, req, b.head);
1285         return 0;
1286 }
1287 
1288 static int
1289 netifd_handle_wdev_get_validate(struct ubus_context *ctx, struct ubus_object *obj,
1290                           struct ubus_request_data *req, const char *method,
1291                           struct blob_attr *msg)
1292 {
1293         struct wireless_device *wdev;
1294         int ret;
1295 
1296         wdev = get_wdev(msg, &ret);
1297         if (ret == UBUS_STATUS_NOT_FOUND)
1298                 return ret;
1299 
1300         blob_buf_init(&b, 0);
1301         if (wdev) {
1302                 wireless_device_get_validate(wdev, &b);
1303         } else {
1304                 vlist_for_each_element(&wireless_devices, wdev, node)
1305                         wireless_device_get_validate(wdev, &b);
1306         }
1307         ubus_send_reply(ctx, req, b.head);
1308         return 0;
1309 }
1310 
1311 static int
1312 netifd_handle_wdev_notify(struct ubus_context *ctx, struct ubus_object *obj,
1313                           struct ubus_request_data *req, const char *method,
1314                           struct blob_attr *msg)
1315 {
1316         struct wireless_device *wdev;
1317         int ret;
1318 
1319         wdev = get_wdev(msg, &ret);
1320         if (!wdev)
1321                 return ret;
1322 
1323         return wireless_device_notify(wdev, msg, req);
1324 }
1325 
1326 static struct ubus_method wireless_object_methods[] = {
1327         { .name = "up", .handler = netifd_handle_wdev_up },
1328         { .name = "down", .handler = netifd_handle_wdev_down },
1329         { .name = "reconf", .handler = netifd_handle_wdev_reconf },
1330         { .name = "status", .handler = netifd_handle_wdev_status },
1331         { .name = "notify", .handler = netifd_handle_wdev_notify },
1332         { .name = "get_validate", .handler = netifd_handle_wdev_get_validate },
1333 };
1334 
1335 static struct ubus_object_type wireless_object_type =
1336         UBUS_OBJECT_TYPE("netifd_iface", wireless_object_methods);
1337 
1338 
1339 static struct ubus_object wireless_object = {
1340         .name = "network.wireless",
1341         .type = &wireless_object_type,
1342         .methods = wireless_object_methods,
1343         .n_methods = ARRAY_SIZE(wireless_object_methods),
1344 };
1345 
1346 int
1347 netifd_extdev_invoke(uint32_t id, const char *method, struct blob_attr *msg,
1348          ubus_data_handler_t data_cb, void *data)
1349 {
1350         return ubus_invoke(ubus_ctx, id, method, msg, data_cb, data, 3000);
1351 }
1352 
1353 int
1354 netifd_ubus_init(const char *path)
1355 {
1356         uloop_init();
1357         ubus_path = path;
1358 
1359         ubus_ctx = ubus_connect(path);
1360         if (!ubus_ctx)
1361                 return -EIO;
1362 
1363         DPRINTF("connected as %08x\n", ubus_ctx->local_id);
1364         ubus_ctx->connection_lost = netifd_ubus_connection_lost;
1365         netifd_ubus_add_fd();
1366 
1367         netifd_add_object(&main_object);
1368         netifd_add_object(&dev_object);
1369         netifd_add_object(&wireless_object);
1370         netifd_add_iface_object();
1371 
1372         return 0;
1373 }
1374 
1375 void
1376 netifd_ubus_done(void)
1377 {
1378         ubus_free(ubus_ctx);
1379 }
1380 
1381 void
1382 netifd_ubus_interface_event(struct interface *iface, bool up)
1383 {
1384         blob_buf_init(&b, 0);
1385         blobmsg_add_string(&b, "action", up ? "ifup" : "ifdown");
1386         blobmsg_add_string(&b, "interface", iface->name);
1387         ubus_send_event(ubus_ctx, "network.interface", b.head);
1388 }
1389 
1390 void
1391 netifd_ubus_interface_notify(struct interface *iface, bool up)
1392 {
1393         const char *event = (up) ? "interface.update" : "interface.down";
1394         blob_buf_init(&b, 0);
1395         blobmsg_add_string(&b, "interface", iface->name);
1396         netifd_dump_status(iface);
1397         ubus_notify(ubus_ctx, &iface_object, event, b.head, -1);
1398         ubus_notify(ubus_ctx, &iface->ubus, event, b.head, -1);
1399 }
1400 
1401 void
1402 netifd_ubus_add_interface(struct interface *iface)
1403 {
1404         struct ubus_object *obj = &iface->ubus;
1405         char *name = NULL;
1406 
1407         if (asprintf(&name, "%s.interface.%s", main_object.name, iface->name) == -1)
1408                 return;
1409 
1410         obj->name = name;
1411         obj->type = &iface_object_type;
1412         obj->methods = iface_object_methods;
1413         obj->n_methods = ARRAY_SIZE(iface_object_methods);
1414         if (ubus_add_object(ubus_ctx, &iface->ubus)) {
1415                 DPRINTF("failed to publish ubus object for interface '%s'\n", iface->name);
1416                 free(name);
1417                 obj->name = NULL;
1418         }
1419 }
1420 
1421 void
1422 netifd_ubus_remove_interface(struct interface *iface)
1423 {
1424         if (!iface->ubus.name)
1425                 return;
1426 
1427         ubus_remove_object(ubus_ctx, &iface->ubus);
1428         free((void *) iface->ubus.name);
1429 }
1430 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt