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

Sources/netifd/config.c

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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt