diff options
-rw-r--r-- | interface-ip.c | 14 | ||||
-rw-r--r-- | interface-ip.h | 4 | ||||
-rw-r--r-- | system-dummy.c | 6 | ||||
-rw-r--r-- | system-linux.c | 103 | ||||
-rw-r--r-- | system.h | 1 | ||||
-rw-r--r-- | ubus.c | 3 |
6 files changed, 90 insertions, 41 deletions
diff --git a/interface-ip.c b/interface-ip.c index bd6f164..715e498 100644 --- a/interface-ip.c +++ b/interface-ip.c @@ -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 diff --git a/interface-ip.h b/interface-ip.h index 93d55ee..a5612e5 100644 --- a/interface-ip.h +++ b/interface-ip.h @@ -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 */ diff --git a/system-dummy.c b/system-dummy.c index bb94781..f2988f2 100644 --- a/system-dummy.c +++ b/system-dummy.c @@ -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; diff --git a/system-linux.c b/system-linux.c index ad3adec..af54bfd 100644 --- a/system-linux.c +++ b/system-linux.c @@ -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) @@ -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); @@ -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); |