From: Jukka Rissanen <jukka.rissa...@linux.intel.com> --- src/connman.h | 2 ++ src/inet.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+)
diff --git a/src/connman.h b/src/connman.h index df24f1e..2617718 100644 --- a/src/connman.h +++ b/src/connman.h @@ -191,6 +191,8 @@ int __connman_inet_rtnl_addattr_l(struct nlmsghdr *n, size_t max_length, int type, const void *data, size_t data_length); int __connman_inet_rtnl_addattr32(struct nlmsghdr *n, size_t maxlen, int type, __u32 data); +int __connman_inet_add_fwmark_rule(int ifindex, int family, uint32_t fwmark); +int __connman_inet_del_fwmark_rule(int ifindex, int family, uint32_t fwmark); #include <connman/resolver.h> diff --git a/src/inet.c b/src/inet.c index 0027fe6..4e6d1c1 100644 --- a/src/inet.c +++ b/src/inet.c @@ -45,6 +45,7 @@ #include <fcntl.h> #include <linux/if_tun.h> #include <ctype.h> +#include <linux/fib_rules.h> #include "connman.h" @@ -2376,3 +2377,79 @@ connman_bool_t connman_inet_is_ipv6_supported() close(sk); return TRUE; } + +static int iprule_modify(int cmd, int family, uint32_t table_id, + uint32_t fwmark) +{ + struct __connman_inet_rtnl_handle rth; + int ret; + + memset(&rth, 0, sizeof(rth)); + + rth.req.n.nlmsg_type = cmd; + rth.req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + rth.req.n.nlmsg_flags = NLM_F_REQUEST; + rth.req.u.r.rt.rtm_family = family; + rth.req.u.r.rt.rtm_protocol = RTPROT_BOOT; + rth.req.u.r.rt.rtm_scope = RT_SCOPE_UNIVERSE; + rth.req.u.r.rt.rtm_table = table_id; + rth.req.u.r.rt.rtm_type = RTN_UNSPEC; + rth.req.u.r.rt.rtm_flags = 0; + + if (cmd == RTM_NEWRULE) { + rth.req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL; + rth.req.u.r.rt.rtm_type = RTN_UNICAST; + } + + __connman_inet_rtnl_addattr32(&rth.req.n, sizeof(rth.req), + FRA_FWMARK, fwmark); + + if (table_id < 256) { + rth.req.u.r.rt.rtm_table = table_id; + } else { + rth.req.u.r.rt.rtm_table = RT_TABLE_UNSPEC; + __connman_inet_rtnl_addattr32(&rth.req.n, sizeof(rth.req), + FRA_TABLE, table_id); + } + + if (rth.req.u.r.rt.rtm_family == AF_UNSPEC) + rth.req.u.r.rt.rtm_family = AF_INET; + + ret = __connman_inet_rtnl_open(&rth); + if (ret < 0) + goto done; + + ret = __connman_inet_rtnl_send(&rth, &rth.req.n); + +done: + __connman_inet_rtnl_close(&rth); + + return ret; +} + +/* + * Tie the table number to interface index number, substract 1 because + * indexes are > 0 + */ +static uint32_t get_table_id(int ifindex) +{ + const uint32_t value = ('c' << 24) | ('m' << 16) | ('a' << 8) | 'n'; + + return value + ifindex - 1; +} + +int __connman_inet_add_fwmark_rule(int ifindex, int family, uint32_t fwmark) +{ + /* ip rule add fwmark 9876 table 1234 */ + + uint32_t table_id = get_table_id(ifindex); + + return iprule_modify(RTM_NEWRULE, family, table_id, fwmark); +} + +int __connman_inet_del_fwmark_rule(int ifindex, int family, uint32_t fwmark) +{ + uint32_t table_id = get_table_id(ifindex); + + return iprule_modify(RTM_DELRULE, family, table_id, fwmark); +} -- 1.8.1.3.566.gaa39828 _______________________________________________ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman