remove obsolete /opt/local prefix on Mac OS X
[project/netifd.git] / proto.c
diff --git a/proto.c b/proto.c
index 3a7b2a8..23304f3 100644 (file)
--- a/proto.c
+++ b/proto.c
@@ -101,6 +101,9 @@ alloc_device_addr(bool v6, bool ext)
        struct device_addr *addr;
 
        addr = calloc(1, sizeof(*addr));
+       if (!addr)
+               return NULL;
+
        addr->flags = v6 ? DEVADDR_INET6 : DEVADDR_INET4;
        if (ext)
                addr->flags |= DEVADDR_EXTERNAL;
@@ -120,17 +123,27 @@ parse_addr(struct interface *iface, const char *str, bool v6, int mask,
                return false;
 
        addr->mask = mask;
-       if (!parse_ip_and_netmask(af, str, &addr->addr, &addr->mask)) {
-               interface_add_error(iface, "proto", "INVALID_ADDRESS", &str, 1);
-               free(addr);
-               return false;
-       }
+       if (!parse_ip_and_netmask(af, str, &addr->addr, &addr->mask))
+               goto error;
+
+       if (!v6) {
+               if (IN_EXPERIMENTAL(ntohl(addr->addr.in.s_addr)))
+                       goto error;
+
+       } else if (IN6_IS_ADDR_MULTICAST(&addr->addr.in6))
+               goto error;
 
        if (broadcast)
                addr->broadcast = broadcast;
 
        vlist_add(&iface->proto_ip.addr, &addr->node, &addr->flags);
        return true;
+
+error:
+       interface_add_error(iface, "proto", "INVALID_ADDRESS", &str, 1);
+       free(addr);
+
+       return false;
 }
 
 static int
@@ -262,6 +275,9 @@ parse_gateway_option(struct interface *iface, struct blob_attr *attr, bool v6)
        int af = v6 ? AF_INET6 : AF_INET;
 
        route = calloc(1, sizeof(*route));
+       if (!route)
+               return NULL;
+
        if (!inet_pton(af, str, &route->nexthop)) {
                interface_add_error(iface, "proto", "INVALID_GATEWAY", &str, 1);
                free(route);
@@ -270,6 +286,7 @@ parse_gateway_option(struct interface *iface, struct blob_attr *attr, bool v6)
 
        route->mask = 0;
        route->flags = (v6 ? DEVADDR_INET6 : DEVADDR_INET4);
+       route->metric = iface->metric;
 
        unsigned int table = (v6) ? iface->ip6table : iface->ip4table;
        if (table) {
@@ -286,7 +303,7 @@ static bool
 parse_prefix_option(struct interface *iface, const char *str, size_t len)
 {
        char buf[128] = {0}, *saveptr;
-       if (len > sizeof(buf))
+       if (len >= sizeof(buf))
                return false;
 
        memcpy(buf, str, len);
@@ -513,6 +530,9 @@ default_proto_attach(const struct proto_handler *h,
        struct interface_proto_state *proto;
 
        proto = calloc(1, sizeof(*proto));
+       if (!proto)
+               return NULL;
+
        proto->free = default_proto_free;
        proto->cb = no_proto_handler;
 
@@ -557,7 +577,14 @@ proto_dump_handlers(struct blob_buf *b)
                                blobmsg_add_string(b, p->config_params->params[i].name, uci_get_validate_string(p->config_params, i));
                        blobmsg_close_table(b, v);
                }
+               blobmsg_add_u8(b, "immediate", !!(p->flags & PROTO_FLAG_IMMEDIATE));
                blobmsg_add_u8(b, "no_device", !!(p->flags & PROTO_FLAG_NODEV));
+               blobmsg_add_u8(b, "init_available", !!(p->flags & PROTO_FLAG_INIT_AVAILABLE));
+               blobmsg_add_u8(b, "renew_available", !!(p->flags & PROTO_FLAG_RENEW_AVAILABLE));
+               blobmsg_add_u8(b, "force_link_default", !!(p->flags & PROTO_FLAG_FORCE_LINK_DEFAULT));
+               blobmsg_add_u8(b, "last_error", !!(p->flags & PROTO_FLAG_LASTERROR));
+               blobmsg_add_u8(b, "teardown_on_l3_link_down", !!(p->flags & PROTO_FLAG_TEARDOWN_ON_L3_LINK_DOWN));
+               blobmsg_add_u8(b, "no_task", !!(p->flags & PROTO_FLAG_NO_TASK));
                blobmsg_close_table(b, c);
        }
 }
@@ -585,16 +612,20 @@ void
 proto_attach_interface(struct interface *iface, const char *proto_name)
 {
        const struct proto_handler *proto = &no_proto;
+       const char *error = NULL;
 
        if (proto_name) {
                proto = get_proto_handler(proto_name);
                if (!proto) {
-                       interface_add_error(iface, "proto", "INVALID_PROTO", NULL, 0);
+                       error = "INVALID_PROTO";
                        proto = &no_proto;
                }
        }
 
        iface->proto_handler = proto;
+
+       if (error)
+               interface_add_error(iface, "proto", error, NULL, 0);
 }
 
 int