aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pingu_iface.c2
-rw-r--r--pingu_netlink.c70
-rw-r--r--pingu_netlink.h7
-rw-r--r--pingu_route.h1
4 files changed, 49 insertions, 31 deletions
diff --git a/pingu_iface.c b/pingu_iface.c
index f92bc5d..fb311a5 100644
--- a/pingu_iface.c
+++ b/pingu_iface.c
@@ -181,7 +181,7 @@ void pingu_iface_update_routes(struct pingu_iface *iface, int action)
struct pingu_route *route;
list_for_each_entry(route, &iface->route_list, route_list_entry) {
if (is_default_gw(route) && iface->has_address)
- kernel_route_modify(action, route, iface, RT_TABLE_MAIN);
+ kernel_route_modify(action, route, RT_TABLE_MAIN);
}
if (load_balanced > 1)
kernel_route_multipath(RTM_NEWROUTE, &iface_list, RT_TABLE_MAIN);
diff --git a/pingu_netlink.c b/pingu_netlink.c
index 107a1f9..9f923f8 100644
--- a/pingu_netlink.c
+++ b/pingu_netlink.c
@@ -17,7 +17,7 @@
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/ip.h>
-#include <linux/if.h>
+#include <net/if.h>
#include <linux/fib_rules.h>
#include <netinet/in.h>
@@ -38,6 +38,11 @@
#include "pingu_host.h"
#include "pingu_netlink.h"
+#ifndef IFF_LOWER_UP
+/* from linux/if.h which conflicts with net/if.h */
+#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */
+#endif
+
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
#endif
@@ -299,8 +304,8 @@ static int netlink_enumerate(struct netlink_fd *fd, int family, int type)
}
int netlink_route_modify(struct netlink_fd *fd, int action_type,
- struct pingu_route *route,
- int iface_index, int table)
+ struct pingu_route *route,
+ int table)
{
struct {
struct nlmsghdr nlh;
@@ -327,7 +332,7 @@ int netlink_route_modify(struct netlink_fd *fd, int action_type,
&route->dest);
netlink_add_rtattr_addr_any(&req.nlh, sizeof(req), RTA_GATEWAY,
&route->gw_addr);
- netlink_add_rtattr_l(&req.nlh, sizeof(req), RTA_OIF, &iface_index, 4);
+ netlink_add_rtattr_l(&req.nlh, sizeof(req), RTA_OIF, &route->dev_index, 4);
if (route->metric != 0)
netlink_add_rtattr_l(&req.nlh, sizeof(req), RTA_PRIORITY,
&route->metric, 4);
@@ -439,16 +444,16 @@ int netlink_route_multipath(struct netlink_fd *fd, int action_type,
int netlink_route_replace_or_add(struct netlink_fd *fd,
struct pingu_route *route,
- int iface_index, int table)
+ int table)
{
- return netlink_route_modify(fd, RTM_NEWROUTE, route, iface_index, table);
+ return netlink_route_modify(fd, RTM_NEWROUTE, route, table);
}
int netlink_route_delete(struct netlink_fd *fd,
struct pingu_route *route,
- int iface_index, int table)
+ int table)
{
- return netlink_route_modify(fd, RTM_DELROUTE, route, iface_index, table);
+ return netlink_route_modify(fd, RTM_DELROUTE, route, table);
}
static void netlink_route_flush(struct netlink_fd *fd, struct pingu_iface *iface)
@@ -456,7 +461,7 @@ static void netlink_route_flush(struct netlink_fd *fd, struct pingu_iface *iface
struct pingu_route *gw;
int err;
list_for_each_entry(gw, &iface->route_list, route_list_entry) {
- err = netlink_route_delete(fd, gw, iface->index, iface->route_table);
+ err = netlink_route_delete(fd, gw, iface->route_table);
if (err > 0)
log_error("%s: Failed to clean up route in table %i: ",
iface->name, iface->route_table, strerror(err));
@@ -492,7 +497,7 @@ int netlink_rule_modify(struct netlink_fd *fd,
if (iface->rule_priority != 0)
netlink_add_rtattr_l(&req.nlh, sizeof(req), FRA_PRIORITY,
&iface->rule_priority, 4);
-
+
if (!netlink_talk(fd, &req.nlh, sizeof(req), &req.nlh))
return -1;
@@ -619,6 +624,7 @@ static struct pingu_route *gw_from_rtmsg(struct pingu_route *gw,
gw->protocol = rtm->rtm_protocol;
gw->scope = rtm->rtm_scope;
gw->type = rtm->rtm_type;
+ gw->dev_index = *(int*)RTA_DATA(rta[RTA_OIF]);
if (rta[RTA_SRC] != NULL)
sockaddr_init(&gw->src, rtm->rtm_family, RTA_DATA(rta[RTA_SRC]));
@@ -634,14 +640,16 @@ static struct pingu_route *gw_from_rtmsg(struct pingu_route *gw,
return gw;
}
-static void log_route_change(struct pingu_route *route,
- char *ifname, int table, int action)
+static void log_route_change(struct pingu_route *route, int table,
+ int action)
{
char deststr[64] = "", gwstr[64] = "", viastr[68] = "";
+ char ifname[IF_NAMESIZE];
char *actionstr = "New";
if (action == RTM_DELROUTE)
actionstr = "Delete";
+ if_indextoname(route->dev_index, ifname);
sockaddr_to_string(&route->dest, deststr, sizeof(deststr));
sockaddr_to_string(&route->gw_addr, gwstr, sizeof(gwstr));
if (gwstr[0] != '\0')
@@ -650,6 +658,23 @@ static void log_route_change(struct pingu_route *route,
deststr, route->dst_len, viastr, ifname, table);
}
+void route_changed_for_iface(struct pingu_iface *iface,
+ struct pingu_route *route, int action)
+{
+ int err = 0;
+ log_route_change(route, iface->route_table, action);
+ /* Kernel will remove the alternate route when we lose the
+ * address so we don't need try remove it ourselves */
+ if (action != RTM_DELROUTE || iface->has_address)
+ err = netlink_route_modify(&talk_fd, action, route,
+ iface->route_table);
+ if (err > 0)
+ log_error("Failed to %s route to table %i",
+ action == RTM_NEWROUTE ? "add" : "delete",
+ iface->route_table);
+ pingu_iface_gw_action(iface, route, action);
+}
+
static void netlink_route_cb_action(struct nlmsghdr *msg, int action)
{
struct pingu_iface *iface;
@@ -657,7 +682,6 @@ static void netlink_route_cb_action(struct nlmsghdr *msg, int action)
struct rtattr *rta[RTA_MAX+1];
struct pingu_route route;
- int err = 0;
/* ignore route changes that we made ourselves via talk_fd */
if (msg->nlmsg_pid == getpid())
@@ -669,21 +693,11 @@ static void netlink_route_cb_action(struct nlmsghdr *msg, int action)
return;
gw_from_rtmsg(&route, rtm, rta);
- iface = pingu_iface_get_by_index(*(int*)RTA_DATA(rta[RTA_OIF]));
+ iface = pingu_iface_get_by_index(route.dev_index);
if (iface == NULL)
return;
- log_route_change(&route, iface->name, iface->route_table, action);
- /* Kernel will remove the alternate route when we lose the
- * address so we don't need try remove it ourselves */
- if (action != RTM_DELROUTE || iface->has_address)
- err = netlink_route_modify(&talk_fd, action, &route,
- iface->index, iface->route_table);
- if (err > 0)
- log_error("Failed to %s route to table %i",
- action == RTM_NEWROUTE ? "add" : "delete",
- iface->route_table);
- pingu_iface_gw_action(iface, &route, action);
+ route_changed_for_iface(iface, &route, action);
}
static void netlink_route_new_cb(struct nlmsghdr *msg)
@@ -768,10 +782,10 @@ error:
int kernel_route_modify(int action, struct pingu_route *route,
- struct pingu_iface *iface, int table)
+ int table)
{
- log_route_change(route, iface->name, table, action);
- return netlink_route_modify(&talk_fd, action, route, iface->index, table);
+ log_route_change(route, table, action);
+ return netlink_route_modify(&talk_fd, action, route, table);
}
int kernel_route_multipath(int action, struct list_head *iface_list, int table)
diff --git a/pingu_netlink.h b/pingu_netlink.h
index d65de1f..9d99a17 100644
--- a/pingu_netlink.h
+++ b/pingu_netlink.h
@@ -6,8 +6,11 @@
int kernel_init(struct ev_loop *loop);
int kernel_route_modify(int action, struct pingu_route *route,
- struct pingu_iface *iface, int table);
-int kernel_route_multipath(int action, struct list_head *iface_list, int table);
+ int table);
+void route_changed_for_iface(struct pingu_iface *iface,
+ struct pingu_route *route, int action);
+int kernel_route_multipath(int action, struct list_head *iface_list,
+ int table);
void kernel_cleanup_iface_routes(struct pingu_iface *iface);
void kernel_close(void);
diff --git a/pingu_route.h b/pingu_route.h
index 5badb10..0d61beb 100644
--- a/pingu_route.h
+++ b/pingu_route.h
@@ -12,6 +12,7 @@ struct pingu_route {
unsigned char src_len;
int metric;
+ int dev_index;
unsigned char protocol;
unsigned char scope;
unsigned char type;