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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt