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