trigger proto attach from config.c
authorFelix Fietkau <nbd@openwrt.org>
Sun, 4 Sep 2011 12:33:31 +0000 (14:33 +0200)
committerFelix Fietkau <nbd@openwrt.org>
Sun, 4 Sep 2011 12:33:31 +0000 (14:33 +0200)
config.c
interface.c
interface.h
proto-static.c
proto.c
proto.h

index 7ba6875..2e00364 100644 (file)
--- a/config.c
+++ b/config.c
@@ -4,6 +4,7 @@
 
 #include "netifd.h"
 #include "interface.h"
+#include "proto.h"
 
 struct uci_context *uci_ctx;
 static struct uci_package *uci_network;
@@ -140,7 +141,9 @@ config_parse_bridge_interface(struct uci_section *s)
 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);
@@ -151,7 +154,11 @@ config_parse_interface(struct uci_section *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;
+
+       proto_init_interface(iface, s);
 }
 
 void
index 20956be..f08fee0 100644 (file)
@@ -201,12 +201,13 @@ void interface_set_proto_state(struct interface *iface, struct interface_proto_s
 }
 
 struct interface *
-interface_alloc(const char *name, struct uci_section *s, struct blob_attr *attr)
+interface_alloc(const char *name, struct blob_attr *attr)
 {
        struct interface *iface;
        struct blob_attr *tb[IFACE_ATTR_MAX];
        struct blob_attr *cur;
        struct device *dev;
+       const char *proto_name = NULL;
 
        iface = interface_get(name);
        if (iface)
@@ -221,19 +222,22 @@ interface_alloc(const char *name, struct uci_section *s, struct blob_attr *attr)
        INIT_LIST_HEAD(&iface->address);
        INIT_LIST_HEAD(&iface->routes);
 
-       proto_attach_interface(iface, s);
-
-       netifd_ubus_add_interface(iface);
-
        blobmsg_parse(iface_attrs, IFACE_ATTR_MAX, tb,
                      blob_data(attr), blob_len(attr));
 
+       if ((cur = tb[IFACE_ATTR_PROTO]))
+               proto_name = blobmsg_data(cur);
+
+       proto_attach_interface(iface, proto_name);
+
        if ((cur = tb[IFACE_ATTR_IFNAME])) {
                dev = device_get(blobmsg_data(cur), true);
                if (dev)
                        device_add_user(&iface->main_dev, dev);
        }
 
+       netifd_ubus_add_interface(iface);
+
        return iface;
 }
 
index 9090164..f66b5b9 100644 (file)
@@ -47,6 +47,7 @@ struct interface {
        struct device_user *l3_iface;
 
        /* primary protocol state */
+       const struct proto_handler *proto_handler;
        struct interface_proto_state *proto;
 
        struct list_head address, routes;
@@ -60,7 +61,7 @@ struct interface {
 extern const struct config_param_list interface_attr_list;
 
 struct interface *interface_get(const char *name);
-struct interface *interface_alloc(const char *name, struct uci_section *s, struct blob_attr *attr);
+struct interface *interface_alloc(const char *name, struct blob_attr *attr);
 void interface_free(struct interface *iface);
 
 void interface_set_proto_state(struct interface *iface, struct interface_proto_state *state);
index 3c251f4..6b4cc23 100644 (file)
@@ -215,7 +215,7 @@ static_free(struct interface_proto_state *proto)
 }
 
 struct interface_proto_state *
-static_attach(struct proto_handler *h, struct interface *iface,
+static_attach(const struct proto_handler *h, struct interface *iface,
              struct uci_section *s)
 {
        struct static_proto_state *state;
diff --git a/proto.c b/proto.c
index 5126107..7242e80 100644 (file)
--- a/proto.c
+++ b/proto.c
@@ -41,22 +41,33 @@ no_proto_handler(struct interface_proto_state *proto,
 }
 
 static struct interface_proto_state *
-get_default_proto(void)
+default_proto_attach(const struct proto_handler *h,
+                    struct interface *iface,
+                    struct uci_section *s)
 {
        struct interface_proto_state *proto;
 
        proto = calloc(1, sizeof(*proto));
        proto->free = default_proto_free;
        proto->flags = PROTO_FLAG_IMMEDIATE;
+       proto->handler = no_proto_handler;
 
        return proto;
 }
 
-struct proto_handler *
+static const struct proto_handler no_proto = {
+       .name = "none",
+       .attach = default_proto_attach,
+};
+
+static const struct proto_handler *
 get_proto_handler(const char *name)
 {
        struct proto_handler *proto;
 
+       if (!strcmp(name, "none"))
+           return &no_proto;
+
        if (!handlers.comp)
                return NULL;
 
@@ -64,44 +75,38 @@ get_proto_handler(const char *name)
 }
 
 void
-proto_attach_interface(struct interface *iface, struct uci_section *s)
+proto_init_interface(struct interface *iface, struct uci_section *s)
 {
+       const struct proto_handler *proto = iface->proto_handler;
        struct interface_proto_state *state = NULL;
-       struct proto_handler *proto = NULL;
-       const char *proto_name;
-       const char *error = NULL;
 
-       proto_name = uci_lookup_option_string(uci_ctx, s, "proto");
-       if (!proto_name) {
-               error = "NO_PROTO";
-               goto error;
-       }
+       if (proto)
+               state = proto->attach(proto, iface, s);
 
-       if (!strcmp(proto_name, "none")) {
-               state = get_default_proto();
-               state->handler = no_proto_handler;
-               goto out;
+       if (!state) {
+               state = no_proto.attach(&no_proto, iface, s);
+               state->handler = invalid_proto_handler;
        }
 
-       proto = get_proto_handler(proto_name);
-       if (!proto) {
-               error = "INVALID_PROTO";
-               goto error;
-       }
+       interface_set_proto_state(iface, state);
+}
 
-       state = proto->attach(proto, iface, s);
+void
+proto_attach_interface(struct interface *iface, const char *proto_name)
+{
+       const struct proto_handler *proto = NULL;
 
-error:
-       if (error) {
-               interface_add_error(iface, "proto", error, NULL, 0);
-               state = get_default_proto();
-               state->handler = invalid_proto_handler;
+       if (!proto_name) {
+               interface_add_error(iface, "proto", "NO_PROTO", NULL, 0);
+               return;
        }
 
-out:
-       interface_set_proto_state(iface, state);
-}
+       proto = get_proto_handler(proto_name);
+       if (!proto)
+               interface_add_error(iface, "proto", "INVALID_PROTO", NULL, 0);
 
+       iface->proto_handler = proto;
+}
 
 int
 interface_proto_event(struct interface_proto_state *proto,
diff --git a/proto.h b/proto.h
index fd9a0f8..332745c 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -32,7 +32,7 @@ struct interface_proto_state {
 };
 
 typedef struct interface_proto_state *
-       (*proto_attach_cb)(struct proto_handler *h, struct interface *,
+       (*proto_attach_cb)(const struct proto_handler *h, struct interface *,
                           struct uci_section *s);
 
 struct proto_handler {
@@ -43,8 +43,8 @@ struct proto_handler {
 };
 
 void add_proto_handler(struct proto_handler *p);
-struct proto_handler *get_proto_handler(const char *name);
-void proto_attach_interface(struct interface *iface, struct uci_section *s);
+void proto_init_interface(struct interface *iface, struct uci_section *s);
+void proto_attach_interface(struct interface *iface, const char *proto_name);
 int interface_proto_event(struct interface_proto_state *proto,
                          enum interface_proto_cmd cmd, bool force);