#include <stdlib.h>
#include <stdio.h>
+#include <uci.h>
+
#include "netifd.h"
#include "interface.h"
+#include "proto.h"
+#include "config.h"
-struct uci_context *uci_ctx;
-static struct uci_package *uci_network;
bool config_init = false;
-static struct blob_buf b;
+static struct uci_context *uci_ctx;
+static struct uci_package *uci_network;
+static struct blob_buf b;
+static unsigned int config_version = 1;
static void uci_attr_to_blob(struct blob_buf *b, const char *str,
const char *name, enum blobmsg_type type)
free(str);
}
-static void uci_to_blob(struct blob_buf *b, struct uci_section *s,
- const struct config_param_list *p)
+static void __uci_to_blob(struct blob_buf *b, struct uci_section *s,
+ const struct config_param_list *p)
{
- const struct blobmsg_policy *attr;
+ const struct blobmsg_policy *attr = NULL;
struct uci_element *e;
struct uci_option *o;
void *array;
}
}
+static void uci_to_blob(struct blob_buf *b, struct uci_section *s,
+ const struct config_param_list *p)
+{
+ int i;
+
+ __uci_to_blob(b, s, p);
+ for (i = 0; i < p->n_next; i++)
+ uci_to_blob(b, s, p->next[i]);
+}
+
+static int
+config_parse_bridge_interface(struct uci_section *s)
+{
+ char *name;
+
+ name = alloca(strlen(s->e.name) + 4);
+ sprintf(name, "br-%s", s->e.name);
+ blobmsg_add_string(&b, "name", name);
+
+ uci_to_blob(&b, s, bridge_device_type.config_params);
+ if (!bridge_device_type.create(b.head)) {
+ DPRINTF("Failed to create bridge for interface '%s'\n", s->e.name);
+ return -EINVAL;
+ }
+
+ blob_buf_init(&b, 0);
+ blobmsg_add_string(&b, "ifname", name);
+ return 0;
+}
+
+void
+config_set_state(struct config_state *state, const struct blob_attr *attr)
+{
+ state->data = malloc(blob_pad_len(attr));
+ if (!state->data)
+ return;
+
+ memcpy(state->data, attr, blob_pad_len(attr));
+}
+
static void
config_parse_interface(struct uci_section *s)
{
+ struct interface *iface;
+ const char *type;
+
DPRINTF("Create interface '%s'\n", s->e.name);
blob_buf_init(&b, 0);
+
+ type = uci_lookup_option_string(uci_ctx, s, "type");
+ if (type && !strcmp(type, "bridge"))
+ if (config_parse_bridge_interface(s))
+ return;
+
uci_to_blob(&b, s, &interface_attr_list);
- interface_alloc(s->e.name, s, b.head);
+ iface = interface_alloc(s->e.name, b.head);
+ if (!iface)
+ return;
+
+ blob_buf_init(&b, 0);
+ if (iface->proto_handler && iface->proto_handler->config_params)
+ uci_to_blob(&b, s, iface->proto_handler->config_params);
+
+ proto_init_interface(iface, b.head);
+ iface->config.version = config_version;
}
-void
-config_device_inits(void)
+static void
+config_init_devices(void)
{
struct uci_element *e;
uci_foreach_element(&uci_network->sections, e) {
struct uci_section *s = uci_to_section(e);
+ const struct device_type *devtype;
+ const char *type;
if (strcmp(s->type, "device") != 0)
continue;
blob_buf_init(&b, 0);
- uci_to_blob(&b, s, &device_attr_list);
- device_create(b.head, s);
+ type = uci_lookup_option_string(uci_ctx, s, "type");
+ if (type && !strcmp(type, "bridge"))
+ devtype = &bridge_device_type;
+ else
+ devtype = &simple_device_type;
+
+ uci_to_blob(&b, s, devtype->config_params);
+ devtype->create(b.head);
}
}
uci_network = p;
config_init = true;
- config_device_inits();
+ config_init_devices();
uci_foreach_element(&p->sections, e) {
struct uci_section *s = uci_to_section(e);
if (!strcmp(s->type, "interface"))
config_parse_interface(s);
}
- device_free_all();
+ device_free_unused(NULL);
config_init = false;
interface_start_pending();