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