From: Jukka Rissanen <[email protected]>
---
src/connman.h | 2 ++
src/inet.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+)
diff --git a/src/connman.h b/src/connman.h
index d9f5c53..aca644d 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.2.rc3.16.gce432ca
_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman