diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2013-08-20 15:48:49 +0200 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2013-08-20 15:48:49 +0200 |
commit | 7476d91f882da665b4d15ef879927cee3d7762e3 (patch) | |
tree | 0c37c2f3742fda73765e0fa41cd5ed024210837c | |
parent | 8a091a690faa26da004e3b05bfc96f5602032c62 (diff) | |
download | pingu-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.
-rw-r--r-- | man/pingu.conf.5.in | 4 | ||||
-rw-r--r-- | pingu_conf.c | 2 | ||||
-rw-r--r-- | pingu_iface.h | 3 | ||||
-rw-r--r-- | pingu_netlink.c | 32 |
4 files changed, 31 insertions, 10 deletions
diff --git a/man/pingu.conf.5.in b/man/pingu.conf.5.in index a33f11e..0c0a96b 100644 --- a/man/pingu.conf.5.in +++ b/man/pingu.conf.5.in @@ -1,4 +1,4 @@ -.Dd October 19, 2011 +.Dd August 20, 2013 .Dt PINGU.CONF 8 Linux .Os @@ -65,6 +65,8 @@ The preference value for the ip rule. .It Cd ping Host to ping to verify that gateway is still up. This is the same as defining a host and bind it to interface. +.It Cd fwmark +Add an additional route rule for configured fwmark integer. .El .Sh HOST CONTEXT diff --git a/pingu_conf.c b/pingu_conf.c index 57629b9..263a1f4 100644 --- a/pingu_conf.c +++ b/pingu_conf.c @@ -162,6 +162,8 @@ static int pingu_conf_read_iface(struct pingu_conf *conf, char *ifname) } else if (strcmp(key, "ping") == 0) { struct pingu_host *host = pingu_conf_new_host(value); host->iface = iface; + } else if (strcmp(key, "fwmark") == 0) { + iface->fwmark = atoi(value); } else { log_error("Unknown keyword '%s' on line %i", key, conf->lineno); diff --git a/pingu_iface.h b/pingu_iface.h index 56ac6d8..cab98fd 100644 --- a/pingu_iface.h +++ b/pingu_iface.h @@ -17,7 +17,7 @@ struct pingu_iface { char *gw_down_action; int hosts_online; int required_hosts_online; - + int index; int has_link; int has_address; @@ -30,6 +30,7 @@ struct pingu_iface { union sockaddr_any primary_addr; int route_table; int rule_priority; + int fwmark; struct list_head iface_list_entry; struct list_head ping_list; struct list_head route_list; 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) |