bridge: add support for defining port member vlans via hotplug ops
[project/netifd.git] / 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 "netifd.h"
22 #include "interface.h"
23 #include "interface-ip.h"
24 #include "iprule.h"
25 #include "proto.h"
26 #include "wireless.h"
27 #include "config.h"
28
29 bool config_init = false;
30
31 static struct uci_context *uci_ctx;
32 static struct uci_package *uci_network;
33 static struct uci_package *uci_wireless;
34 static struct blob_buf b;
35
36 static int
37 config_section_idx(struct uci_section *s)
38 {
39 struct uci_element *e;
40 int idx = 0;
41
42 uci_foreach_element(&uci_wireless->sections, e) {
43 struct uci_section *cur = uci_to_section(e);
44
45 if (s == cur)
46 return idx;
47
48 if (!strcmp(cur->type, s->type))
49 idx++;
50 }
51
52 return -1;
53 }
54
55 static bool
56 config_bridge_has_vlans(const char *br_name)
57 {
58 struct uci_element *e;
59
60 uci_foreach_element(&uci_network->sections, e) {
61 struct uci_section *s = uci_to_section(e);
62 const char *name;
63
64 if (strcmp(s->type, "bridge-vlan") != 0)
65 continue;
66
67 name = uci_lookup_option_string(uci_ctx, s, "device");
68 if (!name)
69 continue;
70
71 if (!strcmp(name, br_name))
72 return true;
73 }
74
75 return false;
76 }
77
78 static void
79 config_fixup_bridge_vlan_filtering(struct uci_section *s, const char *name)
80 {
81 struct uci_ptr ptr = {
82 .p = s->package,
83 .s = s,
84 .option = "vlan_filtering",
85 .value = "1",
86 };
87
88 if (!config_bridge_has_vlans(name))
89 return;
90
91 uci_lookup_ptr(uci_ctx, &ptr, NULL, false);
92 if (ptr.o)
93 return;
94
95 uci_set(uci_ctx, &ptr);
96 }
97
98 static int
99 config_parse_bridge_interface(struct uci_section *s, struct device_type *devtype)
100 {
101 char *name;
102
103 name = alloca(strlen(s->e.name) + strlen(devtype->name_prefix) + 2);
104 sprintf(name, "%s-%s", devtype->name_prefix, s->e.name);
105 blobmsg_add_string(&b, "name", name);
106
107 config_fixup_bridge_vlan_filtering(s, name);
108 uci_to_blob(&b, s, devtype->config_params);
109 if (!device_create(name, devtype, b.head)) {
110 D(INTERFACE, "Failed to create '%s' device for interface '%s'\n",
111 devtype->name, s->e.name);
112 }
113
114 blob_buf_init(&b, 0);
115 blobmsg_add_string(&b, "ifname", name);
116 return 0;
117 }
118
119 static void
120 config_parse_interface(struct uci_section *s, bool alias)
121 {
122 struct interface *iface;
123 const char *type = NULL, *disabled;
124 struct blob_attr *config;
125 bool bridge = false;
126 struct device_type *devtype = NULL;
127
128 disabled = uci_lookup_option_string(uci_ctx, s, "disabled");
129 if (disabled && !strcmp(disabled, "1"))
130 return;
131
132 blob_buf_init(&b, 0);
133
134 if (!alias)
135 type = uci_lookup_option_string(uci_ctx, s, "type");
136
137 if (type)
138 devtype = device_type_get(type);
139
140 if (devtype && devtype->bridge_capability) {
141 if (config_parse_bridge_interface(s, devtype))
142 return;
143
144 bridge = true;
145 }
146
147 uci_to_blob(&b, s, &interface_attr_list);
148
149 iface = interface_alloc(s->e.name, b.head, false);
150 if (!iface)
151 return;
152
153 if (iface->proto_handler && iface->proto_handler->config_params)
154 uci_to_blob(&b, s, iface->proto_handler->config_params);
155
156 if (!bridge && uci_to_blob(&b, s, simple_device_type.config_params))
157 iface->device_config = true;
158
159 config = blob_memdup(b.head);
160 if (!config)
161 goto error;
162
163 if (alias) {
164 if (!interface_add_alias(iface, config))
165 goto error_free_config;
166 } else {
167 if (!interface_add(iface, config))
168 goto error_free_config;
169 }
170 return;
171
172 error_free_config:
173 free(config);
174 error:
175 free(iface);
176 }
177
178 static void
179 config_parse_route(struct uci_section *s, bool v6)
180 {
181 void *route;
182
183 blob_buf_init(&b, 0);
184 route = blobmsg_open_array(&b, "route");
185 uci_to_blob(&b, s, &route_attr_list);
186 blobmsg_close_array(&b, route);
187 interface_ip_add_route(NULL, blob_data(b.head), v6);
188 }
189
190 static void
191 config_parse_neighbor(struct uci_section *s, bool v6)
192 {
193 void *neighbor;
194 blob_buf_init(&b,0);
195 neighbor = blobmsg_open_array(&b, "neighbor");
196 uci_to_blob(&b,s, &neighbor_attr_list);
197 blobmsg_close_array(&b, neighbor);
198 interface_ip_add_neighbor(NULL, blob_data(b.head), v6);
199 }
200
201 static void
202 config_parse_rule(struct uci_section *s, bool v6)
203 {
204 void *rule;
205
206 blob_buf_init(&b, 0);
207 rule = blobmsg_open_array(&b, "rule");
208 uci_to_blob(&b, s, &rule_attr_list);
209 blobmsg_close_array(&b, rule);
210 iprule_add(blob_data(b.head), v6);
211 }
212
213 static void
214 config_init_devices(void)
215 {
216 struct uci_element *e;
217
218 uci_foreach_element(&uci_network->sections, e) {
219 const struct uci_blob_param_list *params = NULL;
220 struct uci_section *s = uci_to_section(e);
221 struct device_type *devtype = NULL;
222 struct device *dev;
223 const char *type, *name;
224
225 if (strcmp(s->type, "device") != 0)
226 continue;
227
228 name = uci_lookup_option_string(uci_ctx, s, "name");
229 if (!name)
230 continue;
231
232 type = uci_lookup_option_string(uci_ctx, s, "type");
233 if (type)
234 devtype = device_type_get(type);
235
236 if (devtype)
237 params = devtype->config_params;
238 if (!params)
239 params = simple_device_type.config_params;
240
241 if (devtype && devtype->bridge_capability)
242 config_fixup_bridge_vlan_filtering(s, name);
243
244 blob_buf_init(&b, 0);
245 uci_to_blob(&b, s, params);
246 if (devtype) {
247 dev = device_create(name, devtype, b.head);
248 if (!dev)
249 continue;
250 } else {
251 dev = device_get(name, 1);
252 if (!dev)
253 continue;
254
255 dev->current_config = true;
256 device_apply_config(dev, dev->type, b.head);
257 }
258 dev->default_config = false;
259 }
260 }
261
262 static void
263 config_parse_vlan(struct device *dev, struct uci_section *s)
264 {
265 enum {
266 BRVLAN_ATTR_VID,
267 BRVLAN_ATTR_LOCAL,
268 BRVLAN_ATTR_PORTS,
269 __BRVLAN_ATTR_MAX,
270 };
271 static const struct blobmsg_policy vlan_attrs[__BRVLAN_ATTR_MAX] = {
272 [BRVLAN_ATTR_VID] = { "vlan", BLOBMSG_TYPE_INT32 },
273 [BRVLAN_ATTR_LOCAL] = { "local", BLOBMSG_TYPE_BOOL },
274 [BRVLAN_ATTR_PORTS] = { "ports", BLOBMSG_TYPE_ARRAY },
275 };
276 static const struct uci_blob_param_info vlan_attr_info[__BRVLAN_ATTR_MAX] = {
277 [BRVLAN_ATTR_PORTS] = { .type = BLOBMSG_TYPE_STRING },
278 };
279 static const struct uci_blob_param_list vlan_attr_list = {
280 .n_params = __BRVLAN_ATTR_MAX,
281 .params = vlan_attrs,
282 .info = vlan_attr_info,
283 };
284 struct blob_attr *tb[__BRVLAN_ATTR_MAX];
285 struct blob_attr *cur;
286 struct bridge_vlan_port *port;
287 struct bridge_vlan *vlan;
288 unsigned int vid;
289 const char *val;
290 char *name_buf;
291 int name_len = 0;
292 int n_ports = 0;
293 int rem;
294
295 val = uci_lookup_option_string(uci_ctx, s, "vlan");
296 if (!val)
297 return;
298
299 blob_buf_init(&b, 0);
300 uci_to_blob(&b, s, &vlan_attr_list);
301 blobmsg_parse(vlan_attrs, __BRVLAN_ATTR_MAX, tb, blob_data(b.head), blob_len(b.head));
302
303 if (!tb[BRVLAN_ATTR_VID])
304 return;
305
306 vid = blobmsg_get_u32(tb[BRVLAN_ATTR_VID]);
307 if (!vid || vid > 4095)
308 return;
309
310 blobmsg_for_each_attr(cur, tb[BRVLAN_ATTR_PORTS], rem) {
311 name_len += strlen(blobmsg_get_string(cur)) + 1;
312 n_ports++;
313 }
314
315 vlan = calloc(1, sizeof(*vlan) + n_ports * sizeof(*port) + name_len);
316 if (!vlan)
317 return;
318
319 vlan->vid = vid;
320 vlan->local = true;
321 if (tb[BRVLAN_ATTR_LOCAL])
322 vlan->local = blobmsg_get_bool(tb[BRVLAN_ATTR_LOCAL]);
323
324 vlan->n_ports = n_ports;
325 vlan->ports = port = (struct bridge_vlan_port *)&vlan[1];
326 INIT_LIST_HEAD(&vlan->hotplug_ports);
327 name_buf = (char *)&port[n_ports];
328
329 blobmsg_for_each_attr(cur, tb[BRVLAN_ATTR_PORTS], rem) {
330 char *sep;
331
332 port->ifname = name_buf;
333 port->flags = BRVLAN_F_UNTAGGED;
334 strcpy(name_buf, blobmsg_get_string(cur));
335
336 sep = strchr(name_buf, ':');
337 if (sep) {
338 for (*sep = 0, sep++; *sep; sep++)
339 switch (*sep) {
340 case '*':
341 port->flags |= BRVLAN_F_PVID;
342 break;
343 case 't':
344 port->flags &= ~BRVLAN_F_UNTAGGED;
345 break;
346 }
347 }
348
349 name_buf += strlen(name_buf) + 1;
350 port++;
351 }
352
353 vlist_add(&dev->vlans, &vlan->node, &vlan->vid);
354 }
355
356
357 static void
358 config_init_vlans(void)
359 {
360 struct uci_element *e;
361 struct device *dev;
362
363 device_vlan_update(false);
364 uci_foreach_element(&uci_network->sections, e) {
365 struct uci_section *s = uci_to_section(e);
366 const char *name;
367
368 if (strcmp(s->type, "bridge-vlan") != 0)
369 continue;
370
371 name = uci_lookup_option_string(uci_ctx, s, "device");
372 if (!name)
373 continue;
374
375 dev = device_get(name, 0);
376 if (!dev || !dev->vlans.update)
377 continue;
378
379 config_parse_vlan(dev, s);
380 }
381 device_vlan_update(true);
382 }
383
384 static struct uci_package *
385 config_init_package(const char *config)
386 {
387 struct uci_context *ctx = uci_ctx;
388 struct uci_package *p = NULL;
389
390 if (!ctx) {
391 ctx = uci_alloc_context();
392 uci_ctx = ctx;
393
394 ctx->flags &= ~UCI_FLAG_STRICT;
395 if (config_path)
396 uci_set_confdir(ctx, config_path);
397
398 #ifdef DUMMY_MODE
399 uci_set_savedir(ctx, "./tmp");
400 #endif
401 } else {
402 p = uci_lookup_package(ctx, config);
403 if (p)
404 uci_unload(ctx, p);
405 }
406
407 if (uci_load(ctx, config, &p))
408 return NULL;
409
410 return p;
411 }
412
413 static void
414 config_init_interfaces(void)
415 {
416 struct uci_element *e;
417
418 uci_foreach_element(&uci_network->sections, e) {
419 struct uci_section *s = uci_to_section(e);
420
421 if (!strcmp(s->type, "interface"))
422 config_parse_interface(s, false);
423 }
424
425 uci_foreach_element(&uci_network->sections, e) {
426 struct uci_section *s = uci_to_section(e);
427
428 if (!strcmp(s->type, "alias"))
429 config_parse_interface(s, true);
430 }
431 }
432
433 static void
434 config_init_ip(void)
435 {
436 struct interface *iface;
437 struct uci_element *e;
438
439 vlist_for_each_element(&interfaces, iface, node)
440 interface_ip_update_start(&iface->config_ip);
441
442 uci_foreach_element(&uci_network->sections, e) {
443 struct uci_section *s = uci_to_section(e);
444
445 if (!strcmp(s->type, "route"))
446 config_parse_route(s, false);
447 else if (!strcmp(s->type, "route6"))
448 config_parse_route(s, true);
449 if (!strcmp(s->type, "neighbor"))
450 config_parse_neighbor(s, false);
451 else if (!strcmp(s->type, "neighbor6"))
452 config_parse_neighbor(s, true);
453 }
454
455 vlist_for_each_element(&interfaces, iface, node)
456 interface_ip_update_complete(&iface->config_ip);
457 }
458
459 static void
460 config_init_rules(void)
461 {
462 struct uci_element *e;
463
464 iprule_update_start();
465
466 uci_foreach_element(&uci_network->sections, e) {
467 struct uci_section *s = uci_to_section(e);
468
469 if (!strcmp(s->type, "rule"))
470 config_parse_rule(s, false);
471 else if (!strcmp(s->type, "rule6"))
472 config_parse_rule(s, true);
473 }
474
475 iprule_update_complete();
476 }
477
478 static void
479 config_init_globals(void)
480 {
481 struct uci_section *globals = uci_lookup_section(
482 uci_ctx, uci_network, "globals");
483 if (!globals)
484 return;
485
486 const char *ula_prefix = uci_lookup_option_string(
487 uci_ctx, globals, "ula_prefix");
488 interface_ip_set_ula_prefix(ula_prefix);
489 }
490
491 static void
492 config_parse_wireless_device(struct uci_section *s)
493 {
494 struct wireless_driver *drv;
495 const char *driver_name;
496
497 driver_name = uci_lookup_option_string(uci_ctx, s, "type");
498 if (!driver_name)
499 return;
500
501 drv = avl_find_element(&wireless_drivers, driver_name, drv, node);
502 if (!drv)
503 return;
504
505 blob_buf_init(&b, 0);
506 uci_to_blob(&b, s, drv->device.config);
507 wireless_device_create(drv, s->e.name, b.head);
508 }
509
510 static struct wireless_interface*
511 config_parse_wireless_interface(struct wireless_device *wdev, struct uci_section *s)
512 {
513 char *name;
514
515 name = alloca(strlen(s->type) + 16);
516 sprintf(name, "@%s[%d]", s->type, config_section_idx(s));
517
518 blob_buf_init(&b, 0);
519 uci_to_blob(&b, s, wdev->drv->interface.config);
520 return wireless_interface_create(wdev, b.head, s->anonymous ? name : s->e.name);
521 }
522
523 static void
524 config_parse_wireless_vlan(struct wireless_device *wdev, char *vif, struct uci_section *s)
525 {
526 char *name;
527
528 name = alloca(strlen(s->type) + 16);
529 sprintf(name, "@%s[%d]", s->type, config_section_idx(s));
530
531 blob_buf_init(&b, 0);
532 uci_to_blob(&b, s, wdev->drv->vlan.config);
533 wireless_vlan_create(wdev, vif, b.head, s->anonymous ? name : s->e.name);
534 }
535
536 static void
537 config_parse_wireless_station(struct wireless_device *wdev, char *vif, struct uci_section *s)
538 {
539 char *name;
540
541 name = alloca(strlen(s->type) + 16);
542 sprintf(name, "@%s[%d]", s->type, config_section_idx(s));
543
544 blob_buf_init(&b, 0);
545 uci_to_blob(&b, s, wdev->drv->station.config);
546 wireless_station_create(wdev, vif, b.head, s->anonymous ? name : s->e.name);
547 }
548
549 static void
550 config_init_wireless(void)
551 {
552 struct wireless_device *wdev;
553 struct uci_element *e;
554 const char *dev_name;
555
556 if (!uci_wireless) {
557 DPRINTF("No wireless configuration found\n");
558 return;
559 }
560
561 vlist_update(&wireless_devices);
562
563 uci_foreach_element(&uci_wireless->sections, e) {
564 struct uci_section *s = uci_to_section(e);
565 if (strcmp(s->type, "wifi-device") != 0)
566 continue;
567
568 config_parse_wireless_device(s);
569 }
570
571 vlist_flush(&wireless_devices);
572
573 vlist_for_each_element(&wireless_devices, wdev, node) {
574 wdev->vif_idx = 0;
575 vlist_update(&wdev->interfaces);
576 wdev->vlan_idx = 0;
577 vlist_update(&wdev->vlans);
578 wdev->sta_idx = 0;
579 vlist_update(&wdev->stations);
580 }
581
582 uci_foreach_element(&uci_wireless->sections, e) {
583 struct uci_section *s = uci_to_section(e);
584 struct wireless_interface *vif;
585 struct uci_element *f;
586
587 if (strcmp(s->type, "wifi-iface") != 0)
588 continue;
589
590 dev_name = uci_lookup_option_string(uci_ctx, s, "device");
591 if (!dev_name)
592 continue;
593
594 wdev = vlist_find(&wireless_devices, dev_name, wdev, node);
595 if (!wdev) {
596 DPRINTF("device %s not found!\n", dev_name);
597 continue;
598 }
599
600 vif = config_parse_wireless_interface(wdev, s);
601
602 if (!vif || s->anonymous)
603 continue;
604 uci_foreach_element(&uci_wireless->sections, f) {
605 struct uci_section *s = uci_to_section(f);
606 const char *vif_name;
607
608 if (strcmp(s->type, "wifi-vlan") != 0)
609 continue;
610
611 vif_name = uci_lookup_option_string(uci_ctx, s, "iface");
612 if (vif_name && strcmp(e->name, vif_name))
613 continue;
614 config_parse_wireless_vlan(wdev, vif->name, s);
615 }
616
617 uci_foreach_element(&uci_wireless->sections, f) {
618 struct uci_section *s = uci_to_section(f);
619 const char *vif_name;
620
621 if (strcmp(s->type, "wifi-station") != 0)
622 continue;
623
624 vif_name = uci_lookup_option_string(uci_ctx, s, "iface");
625 if (vif_name && strcmp(e->name, vif_name))
626 continue;
627 config_parse_wireless_station(wdev, vif->name, s);
628 }
629 }
630
631 vlist_for_each_element(&wireless_devices, wdev, node) {
632 vlist_flush(&wdev->interfaces);
633 vlist_flush(&wdev->vlans);
634 vlist_flush(&wdev->stations);
635 }
636 }
637
638 int
639 config_init_all(void)
640 {
641 int ret = 0;
642 char *err;
643
644 uci_network = config_init_package("network");
645 if (!uci_network) {
646 uci_get_errorstr(uci_ctx, &err, NULL);
647 netifd_log_message(L_CRIT, "Failed to load network config (%s)\n", err);
648 free(err);
649 return -1;
650 }
651
652 uci_wireless = config_init_package("wireless");
653 if (!uci_wireless && uci_ctx->err != UCI_ERR_NOTFOUND) {
654 uci_get_errorstr(uci_ctx, &err, NULL);
655 netifd_log_message(L_CRIT, "Failed to load wireless config (%s)\n", err);
656 free(err);
657 ret = -1;
658 }
659
660 vlist_update(&interfaces);
661 config_init = true;
662 device_lock();
663
664 device_reset_config();
665 config_init_devices();
666 config_init_interfaces();
667 config_init_vlans();
668 config_init_ip();
669 config_init_rules();
670 config_init_globals();
671 config_init_wireless();
672
673 config_init = false;
674 device_unlock();
675
676 device_reset_old();
677 device_init_pending();
678 vlist_flush(&interfaces);
679 device_free_unused(NULL);
680 interface_refresh_assignments(false);
681 interface_start_pending();
682 wireless_start_pending();
683
684 return ret;
685 }