aboutsummaryrefslogtreecommitdiffstats
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
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.
-rw-r--r--man/pingu.conf.5.in4
-rw-r--r--pingu_conf.c2
-rw-r--r--pingu_iface.h3
-rw-r--r--pingu_netlink.c32
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)