netifd: Route type support
authorHans Dedecker <dedeckeh@gmail.com>
Wed, 18 Jun 2014 05:55:48 +0000 (05:55 +0000)
committerSteven Barth <steven@midlink.org>
Wed, 18 Jun 2014 11:02:19 +0000 (13:02 +0200)
Patch adds route type support in netifd by means of the route parameter type.
By default the route type was unicast; the parameter adss support for local/broadcast/multicast/unicast routes which will be put into the appropriate routing table.
If route type parameter is unset the route type will be unicast as before.

Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
interface-ip.c
interface-ip.h
system-dummy.c
system-linux.c
system.h
ubus.c

index bd6f16483a245086cc2170dee7769181e2c79795..715e49837266b7f68b247e10e46d5fc43f9c0f5d 100644 (file)
@@ -39,6 +39,7 @@ enum {
        ROUTE_TABLE,
        ROUTE_SOURCE,
        ROUTE_ONLINK,
+       ROUTE_TYPE,
        __ROUTE_MAX
 };
 
@@ -53,6 +54,7 @@ static const struct blobmsg_policy route_attr[__ROUTE_MAX] = {
        [ROUTE_VALID] = { .name = "valid", .type = BLOBMSG_TYPE_INT32 },
        [ROUTE_SOURCE] = { .name = "source", .type = BLOBMSG_TYPE_STRING },
        [ROUTE_ONLINK] = { .name = "onlink", .type = BLOBMSG_TYPE_BOOL },
+       [ROUTE_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_STRING }
 };
 
 const struct uci_blob_param_list route_attr_list = {
@@ -374,6 +376,14 @@ interface_ip_add_route(struct interface *iface, struct blob_attr *attr, bool v6)
                        route->valid_until = valid_until;
        }
 
+       if ((cur = tb[ROUTE_TYPE]) != NULL) {
+               if (!system_resolve_rt_type(blobmsg_data(cur), &route->type)) {
+                       DPRINTF("Failed to resolve routing type: %s\n", (char *) blobmsg_data(cur));
+                       goto error;
+               }
+               route->flags |= DEVROUTE_TYPE;
+       }
+
        vlist_add(&ip->route, &route->node, route);
        return;
 
@@ -586,7 +596,8 @@ interface_update_proto_route(struct vlist_tree *tree,
 
        if (node_old && node_new)
                keep = !memcmp(&route_old->nexthop, &route_new->nexthop, sizeof(route_old->nexthop)) &&
-                       (route_old->mtu == route_new->mtu) && !route_old->failed;
+                       (route_old->mtu == route_new->mtu) && (route_old->type == route_new->type) &&
+                       !route_old->failed;
 
        if (node_old) {
                if (!(route_old->flags & DEVADDR_EXTERNAL) && route_old->enabled && !keep)
@@ -1223,7 +1234,6 @@ interface_ip_init(struct interface *iface)
        __interface_ip_init(&iface->proto_ip, iface);
        __interface_ip_init(&iface->config_ip, iface);
        vlist_init(&iface->host_routes, route_cmp, interface_update_host_route);
-
 }
 
 static void
index 93d55eee61247fd98de68676fb197a3368e2feff..a5612e5079790f4143e036fe9eb1517ef6ec54f4 100644 (file)
@@ -45,6 +45,9 @@ enum device_addr_flags {
 
        /* route is on-link */
        DEVROUTE_ONLINK         = (1 << 9),
+
+       /* route overrides the default route type */
+       DEVROUTE_TYPE           = (1 << 10),
 };
 
 union if_addr {
@@ -107,6 +110,7 @@ struct device_route {
 
        union if_addr nexthop;
        int mtu;
+       unsigned int type;
        time_t valid_until;
 
        /* must be last */
index bb94781f323cb3c645018496b458951a46f42638..f2988f22ba1547f25a03865871129fdf81d89587 100644 (file)
@@ -193,6 +193,12 @@ int system_flush_routes(void)
        return 0;
 }
 
+bool system_resolve_rt_type(const char *type, unsigned int *id)
+{
+       *id = 0;
+       return true;
+}
+
 bool system_resolve_rt_table(const char *name, unsigned int *id)
 {
        *id = 0;
index ad3adec91a685675cee485cf12c97c2e094d536d..af54bfd8881306857864c49cbc75ff8b1e4d2dc3 100644 (file)
@@ -164,6 +164,46 @@ create_event_socket(struct event_socket *ev, int protocol,
        return true;
 }
 
+static bool
+system_rtn_aton(const char *src, unsigned int *dst)
+{
+       char *e;
+       unsigned int n;
+
+       if (!strcmp(src, "local"))
+               n = RTN_LOCAL;
+       else if (!strcmp(src, "nat"))
+               n = RTN_NAT;
+       else if (!strcmp(src, "broadcast"))
+               n = RTN_BROADCAST;
+       else if (!strcmp(src, "anycast"))
+               n = RTN_ANYCAST;
+       else if (!strcmp(src, "multicast"))
+               n = RTN_MULTICAST;
+       else if (!strcmp(src, "prohibit"))
+               n = RTN_PROHIBIT;
+       else if (!strcmp(src, "unreachable"))
+               n = RTN_UNREACHABLE;
+       else if (!strcmp(src, "blackhole"))
+               n = RTN_BLACKHOLE;
+       else if (!strcmp(src, "xresolve"))
+               n = RTN_XRESOLVE;
+       else if (!strcmp(src, "unicast"))
+               n = RTN_UNICAST;
+       else if (!strcmp(src, "throw"))
+               n = RTN_THROW;
+       else if (!strcmp(src, "failed_policy"))
+               n = RTN_FAILED_POLICY;
+       else {
+               n = strtoul(src, &e, 0);
+               if (!e || *e || e == src || n > 255)
+                       return false;
+       }
+
+       *dst = n;
+       return true;
+}
+
 int system_init(void)
 {
        static struct event_socket rtnl_event;
@@ -1281,9 +1321,6 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd)
                        route->nexthop.in6.s6_addr32[2] ||
                        route->nexthop.in6.s6_addr32[3];
 
-       unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
-                       (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
-
        unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
                        ? route->table : RT_TABLE_MAIN;
 
@@ -1293,7 +1330,7 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd)
                .rtm_src_len = route->sourcemask,
                .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
                .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
-               .rtm_scope = scope,
+               .rtm_scope = RT_SCOPE_NOWHERE,
                .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
                .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
        };
@@ -1306,6 +1343,23 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd)
                        rtm.rtm_scope = RT_SCOPE_UNIVERSE;
                        rtm.rtm_type = RTN_UNREACHABLE;
                }
+               else
+                       rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
+       }
+
+       if (route->flags & DEVROUTE_TYPE) {
+               rtm.rtm_type = route->type;
+               if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
+                       if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
+                           rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
+                               rtm.rtm_table = RT_TABLE_LOCAL;
+               }
+
+               if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT)
+                       rtm.rtm_scope = RT_SCOPE_HOST;
+               else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
+                       rtm.rtm_type == RTN_ANYCAST)
+                       rtm.rtm_scope = RT_SCOPE_LINK;
        }
 
        msg = nlmsg_alloc_simple(cmd, flags);
@@ -1379,6 +1433,11 @@ int system_flush_routes(void)
        return 0;
 }
 
+bool system_resolve_rt_type(const char *type, unsigned int *id)
+{
+       return system_rtn_aton(type, id);
+}
+
 bool system_resolve_rt_table(const char *name, unsigned int *id)
 {
        FILE *f;
@@ -1564,41 +1623,7 @@ int system_flush_iprules(void)
 
 bool system_resolve_iprule_action(const char *action, unsigned int *id)
 {
-       char *e;
-       unsigned int n;
-
-       if (!strcmp(action, "local"))
-               n = RTN_LOCAL;
-       else if (!strcmp(action, "nat"))
-               n = RTN_NAT;
-       else if (!strcmp(action, "broadcast"))
-               n = RTN_BROADCAST;
-       else if (!strcmp(action, "anycast"))
-               n = RTN_ANYCAST;
-       else if (!strcmp(action, "multicast"))
-               n = RTN_MULTICAST;
-       else if (!strcmp(action, "prohibit"))
-               n = RTN_PROHIBIT;
-       else if (!strcmp(action, "unreachable"))
-               n = RTN_UNREACHABLE;
-       else if (!strcmp(action, "blackhole"))
-               n = RTN_BLACKHOLE;
-       else if (!strcmp(action, "xresolve"))
-               n = RTN_XRESOLVE;
-       else if (!strcmp(action, "unicast"))
-               n = RTN_UNICAST;
-       else if (!strcmp(action, "throw"))
-               n = RTN_THROW;
-       else if (!strcmp(action, "failed_policy"))
-               n = RTN_FAILED_POLICY;
-       else {
-               n = strtoul(action, &e, 0);
-               if (!e || *e || e == action || n > 255)
-                       return false;
-       }
-
-       *id = n;
-       return true;
+       return system_rtn_aton(action, id);
 }
 
 time_t system_get_rtime(void)
index 76eee23fb522806952233507c8a70446cf031319..4c80eb0082ec30f53d7ab566bda7878a823ff78f 100644 (file)
--- a/system.h
+++ b/system.h
@@ -128,6 +128,7 @@ int system_add_route(struct device *dev, struct device_route *route);
 int system_del_route(struct device *dev, struct device_route *route);
 int system_flush_routes(void);
 
+bool system_resolve_rt_type(const char *type, unsigned int *id);
 bool system_resolve_rt_table(const char *name, unsigned int *id);
 
 int system_del_ip_tunnel(const char *name);
diff --git a/ubus.c b/ubus.c
index cec2e8881629091d2cb356f7f83e992fbcbde098..9a573c6019bfcf15fad4158ea7460c1a813f7a5b 100644 (file)
--- a/ubus.c
+++ b/ubus.c
@@ -486,6 +486,9 @@ interface_ip_dump_route_list(struct interface_ip_settings *ip, bool enabled)
                inet_ntop(af, &route->nexthop, buf, buflen);
                blobmsg_add_string_buffer(&b);
 
+               if (route->flags & DEVROUTE_TYPE)
+                       blobmsg_add_u32(&b, "type", route->type);
+
                if (route->flags & DEVROUTE_MTU)
                        blobmsg_add_u32(&b, "mtu", route->mtu);