aboutsummaryrefslogtreecommitdiffstats
path: root/pingu_netlink.c
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2013-08-20 15:48:49 +0200
committerNatanael Copa <ncopa@alpinelinux.org>2013-08-20 15:48:49 +0200
commit7476d91f882da665b4d15ef879927cee3d7762e3 (patch)
tree0c37c2f3742fda73765e0fa41cd5ed024210837c /pingu_netlink.c
parent8a091a690faa26da004e3b05bfc96f5602032c62 (diff)
downloadpingu-7476d91f882da665b4d15ef879927cee3d7762e3.tar.bz2
pingu-7476d91f882da665b4d15ef879927cee3d7762e3.tar.xz
pingu: add support for 'fwmark' route rule
Support for adding a fwmark to an interface. It will make it possible to use firewall to mark specific traffic for a specific ISP.
Diffstat (limited to 'pingu_netlink.c')
-rw-r--r--pingu_netlink.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/pingu_netlink.c b/pingu_netlink.c
index 109655d..d149275 100644
--- a/pingu_netlink.c
+++ b/pingu_netlink.c
@@ -476,7 +476,7 @@ static void netlink_route_flush(struct netlink_fd *fd, struct pingu_iface *iface
}
int netlink_rule_modify(struct netlink_fd *fd,
- struct pingu_iface *iface, int type)
+ struct pingu_iface *iface, int rtm_type, int rule_type)
{
struct {
struct nlmsghdr nlh;
@@ -488,8 +488,8 @@ int netlink_rule_modify(struct netlink_fd *fd,
req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
- req.nlh.nlmsg_type = type;
- if (type == RTM_NEWRULE)
+ req.nlh.nlmsg_type = rtm_type;
+ if (rtm_type == RTM_NEWRULE)
req.nlh.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
req.msg.rtm_family = AF_INET;
@@ -498,9 +498,21 @@ int netlink_rule_modify(struct netlink_fd *fd,
req.msg.rtm_scope = RT_SCOPE_UNIVERSE;
req.msg.rtm_type = RTN_UNICAST;
- req.msg.rtm_src_len = 32;
- netlink_add_rtattr_addr_any(&req.nlh, sizeof(req), FRA_SRC,
- &iface->primary_addr);
+ switch (rule_type) {
+ case FRA_SRC:
+ req.msg.rtm_src_len = 32;
+ netlink_add_rtattr_addr_any(&req.nlh, sizeof(req), FRA_SRC,
+ &iface->primary_addr);
+ break;
+ case FRA_FWMARK:
+ netlink_add_rtattr_l(&req.nlh, sizeof(req), FRA_FWMARK,
+ &iface->fwmark, 4);
+ break;
+ default:
+ log_error("%s: unsupported route rule. Should not happen.",
+ iface->name);
+ }
+
if (iface->rule_priority != 0)
netlink_add_rtattr_l(&req.nlh, sizeof(req), FRA_PRIORITY,
&iface->rule_priority, 4);
@@ -513,13 +525,17 @@ int netlink_rule_modify(struct netlink_fd *fd,
int netlink_rule_del(struct netlink_fd *fd, struct pingu_iface *iface)
{
- return netlink_rule_modify(fd, iface, RTM_DELRULE);
+ if (iface->fwmark)
+ netlink_rule_modify(fd, iface, RTM_DELRULE, FRA_FWMARK);
+ return netlink_rule_modify(fd, iface, RTM_DELRULE, FRA_SRC);
}
int netlink_rule_replace_or_add(struct netlink_fd *fd, struct pingu_iface *iface)
{
netlink_rule_del(fd, iface);
- return netlink_rule_modify(fd, iface, RTM_NEWRULE);
+ if (iface->fwmark)
+ netlink_rule_modify(fd, iface, RTM_NEWRULE, FRA_FWMARK);
+ return netlink_rule_modify(fd, iface, RTM_NEWRULE, FRA_SRC);
}
static void netlink_link_new_cb(struct nlmsghdr *msg)