• 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) {
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