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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt