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 #include <string.h> 16 #include <stdlib.h> 17 #include <stdio.h> 18 19 #include <uci.h> 20 21 #include <libubox/blobmsg_json.h> 22 23 #include "netifd.h" 24 #include "interface.h" 25 #include "interface-ip.h" 26 #include "iprule.h" 27 #include "proto.h" 28 #include "wireless.h" 29 #include "config.h" 30 #include "ubus.h" 31 #include "system.h" 32 33 bool config_init = false; 34 35 static struct uci_context *uci_ctx; 36 static struct uci_package *uci_network; 37 static struct uci_package *uci_wireless; 38 static struct blob_attr *board_netdevs; 39 static struct blob_buf b; 40 41 static int 42 config_section_idx(struct uci_section *s) 43 { 44 struct uci_element *e; 45 int idx = 0; 46 47 uci_foreach_element(&uci_wireless->sections, e) { 48 struct uci_section *cur = uci_to_section(e); 49 50 if (s == cur) 51 return idx; 52 53 if (!strcmp(cur->type, s->type)) 54 idx++; 55 } 56 57 return -1; 58 } 59 60 static bool 61 config_bridge_has_vlans(const char *br_name) 62 { 63 struct uci_element *e; 64 65 uci_foreach_element(&uci_network->sections, e) { 66 struct uci_section *s = uci_to_section(e); 67 const char *name; 68 69 if (strcmp(s->type, "bridge-vlan") != 0) 70 continue; 71 72 name = uci_lookup_option_string(uci_ctx, s, "device"); 73 if (!name) 74 continue; 75 76 if (!strcmp(name, br_name)) 77 return true; 78 } 79 80 return false; 81 } 82 83 static void 84 config_fixup_bridge_var(struct uci_section *s, const char *name, const char *val) 85 { 86 struct uci_ptr ptr = { 87 .p = s->package, 88 .s = s, 89 .option = name, 90 .value = val, 91 }; 92 93 uci_lookup_ptr(uci_ctx, &ptr, NULL, false); 94 if (ptr.o) 95 return; 96 97 uci_set(uci_ctx, &ptr); 98 } 99 100 /** 101 * config_fixup_bridge_ports - translate deprecated configs 102 * 103 * Old configs used "ifname" option for specifying bridge ports. For backward 104 * compatibility translate it into the new "ports" option. 105 */ 106 static void config_fixup_bridge_ports(struct uci_section *s) 107 { 108 struct uci_ptr ptr = { 109 .p = s->package, 110 .s = s, 111 .option = "ifname", 112 }; 113 114 if (uci_lookup_option(uci_ctx, s, "ports")) 115 return; 116 117 uci_lookup_ptr(uci_ctx, &ptr, NULL, false); 118 if (!ptr.o) 119 return; 120 121 ptr.value = "ports"; 122 uci_rename(uci_ctx, &ptr); 123 } 124 125 static void 126 config_fixup_bridge_vlan_filtering(struct uci_section *s, const char *name) 127 { 128 bool has_vlans = config_bridge_has_vlans(name); 129 130 config_fixup_bridge_var(s, "__has_vlans", has_vlans ? "1" : ""); 131 132 if (!has_vlans) 133 return; 134 135 config_fixup_bridge_var(s, "vlan_filtering", "1"); 136 } 137 138 static int 139 config_parse_bridge_interface(struct uci_section *s, struct device_type *devtype) 140 { 141 char *name; 142 143 name = alloca(strlen(s->e.name) + strlen(devtype->name_prefix) + 2); 144 sprintf(name, "%s-%s", devtype->name_prefix, s->e.name); 145 blobmsg_add_string(&b, "name", name); 146 147 config_fixup_bridge_ports(s); 148 config_fixup_bridge_vlan_filtering(s, name); 149 uci_to_blob(&b, s, devtype->config_params); 150 if (!device_create(name, devtype, b.head)) { 151 D(INTERFACE, "Failed to create '%s' device for interface '%s'", 152 devtype->name, s->e.name); 153 } 154 155 blob_buf_init(&b, 0); 156 blobmsg_add_string(&b, "ifname", name); 157 return 0; 158 } 159 160 static void 161 config_parse_interface(struct uci_section *s, bool alias) 162 { 163 struct interface *iface; 164 const char *type = NULL, *disabled; 165 struct blob_attr *config; 166 bool bridge = false; 167 struct device_type *devtype = NULL; 168 169 disabled = uci_lookup_option_string(uci_ctx, s, "disabled"); 170 if (disabled && !strcmp(disabled, "1")) 171 return; 172 173 blob_buf_init(&b, 0); 174 175 if (!alias) 176 type = uci_lookup_option_string(uci_ctx, s, "type"); 177 178 if (type) 179 devtype = device_type_get(type); 180 181 if (devtype && devtype->bridge_capability) { 182 if (config_parse_bridge_interface(s, devtype)) 183 return; 184 185 bridge = true; 186 } 187 188 uci_to_blob(&b, s, &interface_attr_list); 189 190 iface = interface_alloc(s->e.name, b.head, false); 191 if (!iface) 192 return; 193 194 if (iface->proto_handler && iface->proto_handler->config_params) 195 uci_to_blob(&b, s, iface->proto_handler->config_params); 196 197 if (!bridge && uci_to_blob(&b, s, simple_device_type.config_params)) 198 iface->device_config = true; 199 200 config = blob_memdup(b.head); 201 if (!config) 202 goto error; 203 204 if (alias) { 205 if (!interface_add_alias(iface, config)) 206 goto error_free_config; 207 } else { 208 if (!interface_add(iface, config)) 209 goto error_free_config; 210 } 211 return; 212 213 error_free_config: 214 free(config); 215 error: 216 free(iface); 217 } 218 219 static void 220 config_parse_route(struct uci_section *s, bool v6) 221 { 222 void *route; 223 224 blob_buf_init(&b, 0); 225 route = blobmsg_open_array(&b, "route"); 226 uci_to_blob(&b, s, &route_attr_list); 227 blobmsg_close_array(&b, route); 228 interface_ip_add_route(NULL, blob_data(b.head), v6); 229 } 230 231 static void 232 config_parse_neighbor(struct uci_section *s, bool v6) 233 { 234 void *neighbor; 235 blob_buf_init(&b,0); 236 neighbor = blobmsg_open_array(&b, "neighbor"); 237 uci_to_blob(&b,s, &neighbor_attr_list); 238 blobmsg_close_array(&b, neighbor); 239 interface_ip_add_neighbor(NULL, blob_data(b.head), v6); 240 } 241 242 static void 243 config_parse_rule(struct uci_section *s, bool v6) 244 { 245 void *rule; 246 247 blob_buf_init(&b, 0); 248 rule = blobmsg_open_array(&b, "rule"); 249 uci_to_blob(&b, s, &rule_attr_list); 250 blobmsg_close_array(&b, rule); 251 iprule_add(blob_data(b.head), v6); 252 } 253 254 static void 255 config_init_devices(bool bridge) 256 { 257 struct uci_element *e; 258 259 uci_foreach_element(&uci_network->sections, e) { 260 const struct uci_blob_param_list *params = NULL; 261 struct uci_section *s = uci_to_section(e); 262 struct device_type *devtype = NULL; 263 struct device *dev; 264 const char *type, *name; 265 266 if (strcmp(s->type, "device") != 0) 267 continue; 268 269 name = uci_lookup_option_string(uci_ctx, s, "name"); 270 if (!name) 271 continue; 272 273 type = uci_lookup_option_string(uci_ctx, s, "type"); 274 if (type) 275 devtype = device_type_get(type); 276 277 if (bridge != (devtype && devtype->bridge_capability)) 278 continue; 279 280 if (devtype) 281 params = devtype->config_params; 282 if (!params) 283 params = simple_device_type.config_params; 284 285 if (devtype && devtype->bridge_capability) { 286 config_fixup_bridge_ports(s); 287 config_fixup_bridge_vlan_filtering(s, name); 288 } 289 290 blob_buf_init(&b, 0); 291 uci_to_blob(&b, s, params); 292 if (devtype) { 293 dev = device_create(name, devtype, b.head); 294 if (!dev) 295 continue; 296 } else { 297 dev = device_get(name, 1); 298 if (!dev) 299 continue; 300 301 dev->current_config = true; 302 device_apply_config(dev, dev->type, b.head); 303 } 304 dev->default_config = false; 305 } 306 } 307 308 static void 309 config_parse_vlan(struct device *dev, struct uci_section *s) 310 { 311 enum { 312 BRVLAN_ATTR_VID, 313 BRVLAN_ATTR_LOCAL, 314 BRVLAN_ATTR_PORTS, 315 BRVLAN_ATTR_ALIAS, 316 __BRVLAN_ATTR_MAX, 317 }; 318 static const struct blobmsg_policy vlan_attrs[__BRVLAN_ATTR_MAX] = { 319 [BRVLAN_ATTR_VID] = { "vlan", BLOBMSG_TYPE_INT32 }, 320 [BRVLAN_ATTR_LOCAL] = { "local", BLOBMSG_TYPE_BOOL }, 321 [BRVLAN_ATTR_PORTS] = { "ports", BLOBMSG_TYPE_ARRAY }, 322 [BRVLAN_ATTR_ALIAS] = { "alias", BLOBMSG_TYPE_ARRAY }, 323 }; 324 static const struct uci_blob_param_info vlan_attr_info[__BRVLAN_ATTR_MAX] = { 325 [BRVLAN_ATTR_PORTS] = { .type = BLOBMSG_TYPE_STRING }, 326 [BRVLAN_ATTR_ALIAS] = { .type = BLOBMSG_TYPE_STRING }, 327 }; 328 static const struct uci_blob_param_list vlan_attr_list = { 329 .n_params = __BRVLAN_ATTR_MAX, 330 .params = vlan_attrs, 331 .info = vlan_attr_info, 332 }; 333 struct blob_attr *tb[__BRVLAN_ATTR_MAX]; 334 struct blob_attr *cur; 335 struct bridge_vlan_port *port; 336 struct bridge_vlan *vlan; 337 unsigned int vid; 338 const char *val; 339 char *name_buf; 340 int name_len = 0; 341 int n_ports = 0; 342 size_t rem; 343 344 val = uci_lookup_option_string(uci_ctx, s, "vlan"); 345 if (!val) 346 return; 347 348 blob_buf_init(&b, 0); 349 uci_to_blob(&b, s, &vlan_attr_list); 350 blobmsg_parse(vlan_attrs, __BRVLAN_ATTR_MAX, tb, blob_data(b.head), blob_len(b.head)); 351 352 if (!tb[BRVLAN_ATTR_VID]) 353 return; 354 355 vid = blobmsg_get_u32(tb[BRVLAN_ATTR_VID]); 356 if (!vid || vid > 4095) 357 return; 358 359 blobmsg_for_each_attr(cur, tb[BRVLAN_ATTR_PORTS], rem) { 360 name_len += strlen(blobmsg_get_string(cur)) + 1; 361 n_ports++; 362 } 363 364 vlan = calloc(1, sizeof(*vlan) + n_ports * sizeof(*port) + name_len); 365 if (!vlan) 366 return; 367 368 vlan->vid = vid; 369 vlan->local = true; 370 if (tb[BRVLAN_ATTR_LOCAL]) 371 vlan->local = blobmsg_get_bool(tb[BRVLAN_ATTR_LOCAL]); 372 373 vlan->n_ports = n_ports; 374 vlan->ports = port = (struct bridge_vlan_port *)&vlan[1]; 375 INIT_LIST_HEAD(&vlan->hotplug_ports); 376 name_buf = (char *)&port[n_ports]; 377 378 blobmsg_for_each_attr(cur, tb[BRVLAN_ATTR_PORTS], rem) { 379 char *sep; 380 381 port->ifname = name_buf; 382 port->flags = BRVLAN_F_UNTAGGED; 383 strcpy(name_buf, blobmsg_get_string(cur)); 384 385 sep = strchr(name_buf, ':'); 386 if (sep) { 387 for (*sep = 0, sep++; *sep; sep++) 388 switch (*sep) { 389 case '*': 390 port->flags |= BRVLAN_F_PVID; 391 break; 392 case 't': 393 port->flags &= ~BRVLAN_F_UNTAGGED; 394 break; 395 } 396 } 397 398 name_buf += strlen(name_buf) + 1; 399 port++; 400 } 401 402 blobmsg_for_each_attr(cur, tb[BRVLAN_ATTR_ALIAS], rem) 403 kvlist_set(&dev->vlan_aliases, blobmsg_get_string(cur), &vid); 404 405 vlist_add(&dev->vlans, &vlan->node, &vlan->vid); 406 } 407 408 409 static void 410 config_init_vlans(void) 411 { 412 struct uci_element *e; 413 struct device *dev; 414 415 device_vlan_update(false); 416 uci_foreach_element(&uci_network->sections, e) { 417 struct uci_section *s = uci_to_section(e); 418 const char *name; 419 420 if (strcmp(s->type, "bridge-vlan") != 0) 421 continue; 422 423 name = uci_lookup_option_string(uci_ctx, s, "device"); 424 if (!name) 425 continue; 426 427 dev = device_get(name, 0); 428 if (!dev || !dev->vlans.update) 429 continue; 430 431 config_parse_vlan(dev, s); 432 } 433 device_vlan_update(true); 434 } 435 436 static struct uci_package * 437 config_init_package(const char *config) 438 { 439 struct uci_context *ctx = uci_ctx; 440 struct uci_package *p = NULL; 441 442 if (!ctx) { 443 ctx = uci_alloc_context(); 444 uci_ctx = ctx; 445 446 ctx->flags &= ~UCI_FLAG_STRICT; 447 if (config_path) 448 uci_set_confdir(ctx, config_path); 449 450 #ifdef DUMMY_MODE 451 uci_set_savedir(ctx, "./tmp"); 452 #endif 453 } else { 454 p = uci_lookup_package(ctx, config); 455 if (p) 456 uci_unload(ctx, p); 457 } 458 459 if (uci_load(ctx, config, &p)) 460 return NULL; 461 462 return p; 463 } 464 465 static void 466 config_init_interfaces(void) 467 { 468 struct uci_element *e; 469 470 uci_foreach_element(&uci_network->sections, e) { 471 struct uci_section *s = uci_to_section(e); 472 473 if (!strcmp(s->type, "interface")) 474 config_parse_interface(s, false); 475 } 476 477 uci_foreach_element(&uci_network->sections, e) { 478 struct uci_section *s = uci_to_section(e); 479 480 if (!strcmp(s->type, "alias")) 481 config_parse_interface(s, true); 482 } 483 } 484 485 static void 486 config_init_ip(void) 487 { 488 struct interface *iface; 489 struct uci_element *e; 490 491 vlist_for_each_element(&interfaces, iface, node) 492 interface_ip_update_start(&iface->config_ip); 493 494 uci_foreach_element(&uci_network->sections, e) { 495 struct uci_section *s = uci_to_section(e); 496 497 if (!strcmp(s->type, "route")) 498 config_parse_route(s, false); 499 else if (!strcmp(s->type, "route6")) 500 config_parse_route(s, true); 501 if (!strcmp(s->type, "neighbor")) 502 config_parse_neighbor(s, false); 503 else if (!strcmp(s->type, "neighbor6")) 504 config_parse_neighbor(s, true); 505 } 506 507 vlist_for_each_element(&interfaces, iface, node) 508 interface_ip_update_complete(&iface->config_ip); 509 } 510 511 static void 512 config_init_rules(void) 513 { 514 struct uci_element *e; 515 516 iprule_update_start(); 517 518 uci_foreach_element(&uci_network->sections, e) { 519 struct uci_section *s = uci_to_section(e); 520 521 if (!strcmp(s->type, "rule")) 522 config_parse_rule(s, false); 523 else if (!strcmp(s->type, "rule6")) 524 config_parse_rule(s, true); 525 } 526 527 iprule_update_complete(); 528 } 529 530 static void 531 config_init_globals(void) 532 { 533 struct uci_section *globals = uci_lookup_section( 534 uci_ctx, uci_network, "globals"); 535 if (!globals) 536 return; 537 538 const char *ula_prefix = uci_lookup_option_string( 539 uci_ctx, globals, "ula_prefix"); 540 interface_ip_set_ula_prefix(ula_prefix); 541 542 const char *tcp_l3mdev = uci_lookup_option_string( 543 uci_ctx, globals, "tcp_l3mdev"); 544 if (tcp_l3mdev) 545 system_tcp_l3mdev(!strcmp(tcp_l3mdev, "1")); 546 547 const char *udp_l3mdev = uci_lookup_option_string( 548 uci_ctx, globals, "udp_l3mdev"); 549 if (udp_l3mdev) 550 system_udp_l3mdev(!strcmp(udp_l3mdev, "1")); 551 } 552 553 static void 554 config_parse_wireless_device(struct uci_section *s) 555 { 556 struct wireless_driver *drv; 557 const char *driver_name; 558 559 driver_name = uci_lookup_option_string(uci_ctx, s, "type"); 560 if (!driver_name) 561 return; 562 563 drv = avl_find_element(&wireless_drivers, driver_name, drv, node); 564 if (!drv) 565 return; 566 567 blob_buf_init(&b, 0); 568 uci_to_blob(&b, s, drv->device.config); 569 wireless_device_create(drv, s->e.name, b.head); 570 } 571 572 static void 573 config_parse_wireless_vlan(struct wireless_interface *vif, struct uci_section *s) 574 { 575 char *name; 576 577 name = alloca(strlen(s->type) + 16); 578 sprintf(name, "@%s[%d]", s->type, config_section_idx(s)); 579 580 blob_buf_init(&b, 0); 581 uci_to_blob(&b, s, vif->wdev->drv->vlan.config); 582 wireless_vlan_create(vif, b.head, s->anonymous ? name : s->e.name); 583 } 584 585 static void 586 config_parse_wireless_station(struct wireless_interface *vif, struct uci_section *s) 587 { 588 char *name; 589 590 name = alloca(strlen(s->type) + 16); 591 sprintf(name, "@%s[%d]", s->type, config_section_idx(s)); 592 593 blob_buf_init(&b, 0); 594 uci_to_blob(&b, s, vif->wdev->drv->station.config); 595 wireless_station_create(vif, b.head, s->anonymous ? name : s->e.name); 596 } 597 598 static void 599 config_wdev_parse_wireless_interface(struct wireless_device *wdev, struct uci_section *s) 600 { 601 struct wireless_interface *vif; 602 struct uci_element *f; 603 char *name; 604 605 name = alloca(strlen(s->type) + 16); 606 sprintf(name, "@%s[%d]", s->type, config_section_idx(s)); 607 608 blob_buf_init(&b, 0); 609 uci_to_blob(&b, s, wdev->drv->interface.config); 610 vif = wireless_interface_create(wdev, b.head, s->anonymous ? name : s->e.name); 611 if (!vif) 612 return; 613 614 if (s->anonymous) 615 goto out; 616 617 uci_foreach_element(&uci_wireless->sections, f) { 618 struct uci_section *cur = uci_to_section(f); 619 const char *vif_name; 620 621 if (strcmp(cur->type, "wifi-vlan") != 0) 622 continue; 623 624 vif_name = uci_lookup_option_string(uci_ctx, cur, "iface"); 625 if (vif_name && strcmp(s->e.name, vif_name)) 626 continue; 627 config_parse_wireless_vlan(vif, cur); 628 } 629 630 uci_foreach_element(&uci_wireless->sections, f) { 631 struct uci_section *cur = uci_to_section(f); 632 const char *vif_name; 633 634 if (strcmp(cur->type, "wifi-station") != 0) 635 continue; 636 637 vif_name = uci_lookup_option_string(uci_ctx, cur, "iface"); 638 if (vif_name && strcmp(s->e.name, vif_name)) 639 continue; 640 config_parse_wireless_station(vif, cur); 641 } 642 643 out: 644 vlist_flush(&vif->vlans); 645 vlist_flush(&vif->stations); 646 } 647 648 static void 649 config_init_procd_wireless_interface(const char *wdev_name, const char *vif_name, 650 struct blob_attr *config, 651 struct blob_attr *vlans, 652 struct blob_attr *stations) 653 { 654 struct wireless_interface *vif; 655 struct wireless_device *wdev; 656 struct blob_attr *cur; 657 char name[16]; 658 int idx = 0; 659 size_t rem; 660 661 wdev = vlist_find(&wireless_devices, wdev_name, wdev, node); 662 if (!wdev) { 663 D(WIRELESS, "device %s not found!", wdev_name); 664 return; 665 } 666 667 vif = wireless_interface_create(wdev, config, vif_name); 668 if (!vif) 669 return; 670 671 blobmsg_for_each_attr(cur, vlans, rem) { 672 snprintf(name, sizeof(name), "%d", ++idx); 673 wireless_vlan_create(vif, cur, name); 674 } 675 676 blobmsg_for_each_attr(cur, stations, rem) { 677 snprintf(name, sizeof(name), "%d", ++idx); 678 wireless_station_create(vif, cur, name); 679 } 680 681 vlist_flush(&vif->vlans); 682 vlist_flush(&vif->stations); 683 } 684 685 static void 686 config_procd_wireless_interface_cb(struct blob_attr *data) 687 { 688 enum { 689 UDATA_ATTR_DEVICE, 690 UDATA_ATTR_CONFIG, 691 UDATA_ATTR_STATIONS, 692 UDATA_ATTR_VLANS, 693 __UDATA_ATTR_MAX, 694 }; 695 static const struct blobmsg_policy policy[__UDATA_ATTR_MAX] = { 696 [UDATA_ATTR_DEVICE] = { "device", BLOBMSG_TYPE_STRING }, 697 [UDATA_ATTR_CONFIG] = { "config", BLOBMSG_TYPE_TABLE }, 698 [UDATA_ATTR_STATIONS] = { "stations", BLOBMSG_TYPE_ARRAY }, 699 [UDATA_ATTR_VLANS] = { "vlans", BLOBMSG_TYPE_ARRAY }, 700 }; 701 struct blob_attr *tb[__UDATA_ATTR_MAX]; 702 const char *dev; 703 704 blobmsg_parse_attr(policy, __UDATA_ATTR_MAX, tb, data); 705 if (!tb[UDATA_ATTR_DEVICE] || !tb[UDATA_ATTR_CONFIG]) 706 return; 707 708 dev = blobmsg_get_string(tb[UDATA_ATTR_DEVICE]); 709 config_init_procd_wireless_interface(dev, blobmsg_name(data), 710 tb[UDATA_ATTR_CONFIG], 711 tb[UDATA_ATTR_VLANS], 712 tb[UDATA_ATTR_STATIONS]); 713 } 714 715 static void 716 config_parse_wireless_interface(const char *dev_name, struct uci_section *s) 717 { 718 struct wireless_device *wdev; 719 720 wdev = vlist_find(&wireless_devices, dev_name, wdev, node); 721 if (!wdev) { 722 D(WIRELESS, "device %s not found!", dev_name); 723 return; 724 } 725 726 config_wdev_parse_wireless_interface(wdev, s); 727 } 728 729 static void 730 config_init_wireless(void) 731 { 732 struct wireless_device *wdev; 733 struct uci_element *e; 734 735 if (!uci_wireless) { 736 D(WIRELESS, "No wireless configuration found"); 737 return; 738 } 739 740 vlist_update(&wireless_devices); 741 742 uci_foreach_element(&uci_wireless->sections, e) { 743 struct uci_section *s = uci_to_section(e); 744 if (strcmp(s->type, "wifi-device") != 0) 745 continue; 746 747 config_parse_wireless_device(s); 748 } 749 750 vlist_flush(&wireless_devices); 751 752 vlist_for_each_element(&wireless_devices, wdev, node) { 753 wdev->vif_idx = 0; 754 vlist_update(&wdev->interfaces); 755 } 756 757 uci_foreach_element(&uci_wireless->sections, e) { 758 struct uci_section *s = uci_to_section(e); 759 struct uci_element *val; 760 struct uci_option *o; 761 762 if (strcmp(s->type, "wifi-iface") != 0) 763 continue; 764 765 o = uci_lookup_option(uci_ctx, s, "device"); 766 if (!o) 767 continue; 768 769 if (o->type == UCI_TYPE_STRING) { 770 config_parse_wireless_interface(o->v.string, s); 771 continue; 772 } 773 774 uci_foreach_element(&o->v.list, val) 775 config_parse_wireless_interface(val->name, s); 776 } 777 778 netifd_ubus_get_procd_data("wifi-iface", config_procd_wireless_interface_cb); 779 780 vlist_for_each_element(&wireless_devices, wdev, node) 781 vlist_flush(&wdev->interfaces); 782 } 783 784 785 static struct blob_attr * 786 config_find_blobmsg_attr(struct blob_attr *attr, const char *name, int type) 787 { 788 struct blobmsg_policy policy = { .name = name, .type = type }; 789 struct blob_attr *cur; 790 791 blobmsg_parse(&policy, 1, &cur, blobmsg_data(attr), blobmsg_len(attr)); 792 793 return cur; 794 } 795 796 struct ether_addr *config_get_default_macaddr(const char *ifname) 797 { 798 struct blob_attr *cur; 799 800 if (!board_netdevs) 801 return NULL; 802 803 cur = config_find_blobmsg_attr(board_netdevs, ifname, BLOBMSG_TYPE_TABLE); 804 if (!cur) 805 return NULL; 806 807 cur = config_find_blobmsg_attr(cur, "macaddr", BLOBMSG_TYPE_STRING); 808 if (!cur) 809 return NULL; 810 811 return ether_aton(blobmsg_get_string(cur)); 812 } 813 814 int config_get_default_gro(const char *ifname) 815 { 816 struct blob_attr *cur; 817 818 if (!board_netdevs) 819 return -1; 820 821 cur = config_find_blobmsg_attr(board_netdevs, ifname, BLOBMSG_TYPE_TABLE); 822 if (!cur) 823 return -1; 824 825 cur = config_find_blobmsg_attr(cur, "gro", BLOBMSG_TYPE_BOOL); 826 if (!cur) 827 return -1; 828 829 return blobmsg_get_bool(cur); 830 } 831 832 const char *config_get_default_conduit(const char *ifname) 833 { 834 struct blob_attr *cur; 835 836 if (!board_netdevs) 837 return NULL; 838 839 cur = config_find_blobmsg_attr(board_netdevs, ifname, BLOBMSG_TYPE_TABLE); 840 if (!cur) 841 return NULL; 842 843 cur = config_find_blobmsg_attr(cur, "conduit", BLOBMSG_TYPE_STRING); 844 if (!cur) 845 return NULL; 846 847 return blobmsg_get_string(cur); 848 } 849 850 static void 851 config_init_board(void) 852 { 853 struct blob_attr *cur; 854 855 blob_buf_init(&b, 0); 856 857 if (!blobmsg_add_json_from_file(&b, DEFAULT_BOARD_JSON)) 858 return; 859 860 free(board_netdevs); 861 board_netdevs = NULL; 862 863 cur = config_find_blobmsg_attr(b.head, "network_device", 864 BLOBMSG_TYPE_TABLE); 865 if (!cur) 866 return; 867 868 board_netdevs = blob_memdup(cur); 869 } 870 871 int 872 config_init_all(void) 873 { 874 int ret = 0; 875 char *err; 876 877 uci_network = config_init_package("network"); 878 if (!uci_network) { 879 uci_get_errorstr(uci_ctx, &err, NULL); 880 netifd_log_message(L_CRIT, "Failed to load network config (%s)\n", err); 881 free(err); 882 return -1; 883 } 884 885 uci_wireless = config_init_package("wireless"); 886 if (!uci_wireless && uci_ctx->err != UCI_ERR_NOTFOUND) { 887 uci_get_errorstr(uci_ctx, &err, NULL); 888 netifd_log_message(L_CRIT, "Failed to load wireless config (%s)\n", err); 889 free(err); 890 ret = -1; 891 } 892 893 config_init_board(); 894 895 vlist_update(&interfaces); 896 config_init = true; 897 898 device_reset_config(); 899 config_init_devices(true); 900 config_init_vlans(); 901 config_init_devices(false); 902 config_init_interfaces(); 903 config_init_ip(); 904 config_init_rules(); 905 config_init_globals(); 906 config_init_wireless(); 907 908 config_init = false; 909 910 device_reset_old(); 911 device_init_pending(); 912 vlist_flush(&interfaces); 913 interface_refresh_assignments(false); 914 interface_start_pending(); 915 wireless_start_pending(0); 916 917 return ret; 918 } 919
This page was automatically generated by LXR 0.3.1. • OpenWrt