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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt