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