diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | pingu_gateway.c | 128 | ||||
-rw-r--r-- | pingu_gateway.h | 30 | ||||
-rw-r--r-- | pingu_iface.c | 20 | ||||
-rw-r--r-- | pingu_iface.h | 6 | ||||
-rw-r--r-- | pingu_netlink.c | 24 | ||||
-rw-r--r-- | pingu_netlink.h | 2 | ||||
-rw-r--r-- | pingu_route.c | 128 | ||||
-rw-r--r-- | pingu_route.h | 30 |
9 files changed, 185 insertions, 185 deletions
@@ -32,11 +32,11 @@ pingu_OBJS = \ pingu_adm.o \ pingu_burst.o \ pingu_conf.o \ - pingu_gateway.o \ pingu_host.o \ pingu_iface.o \ pingu_netlink.o \ pingu_ping.o \ + pingu_route.o \ sockaddr_util.o \ xlib.o diff --git a/pingu_gateway.c b/pingu_gateway.c deleted file mode 100644 index de9b094..0000000 --- a/pingu_gateway.c +++ /dev/null @@ -1,128 +0,0 @@ - -#include <stdlib.h> -#include <string.h> - -#include "list.h" -#include "log.h" -#include "pingu_gateway.h" - -static void pingu_gateway_add_sorted(struct list_head *gateway_list, - struct pingu_gateway *new_gw) -{ - struct pingu_gateway *gw; - list_for_each_entry(gw, gateway_list, gateway_list_entry) { - if (gw->metric > new_gw->metric) { - list_add_tail(&new_gw->gateway_list_entry, - &gw->gateway_list_entry); - return; - } - } - list_add_tail(&new_gw->gateway_list_entry, gateway_list); -} - -static struct pingu_gateway *pingu_gateway_clone(struct pingu_gateway *gw) -{ - struct pingu_gateway *new_gw = calloc(1, sizeof(struct pingu_gateway)); - if (gw == NULL) { - log_perror("Failed to allocate gateway"); - return NULL; - } - /* copy the fields without overwriting the list entry */ - memcpy(&new_gw->dest, &gw->dest, sizeof(new_gw->dest)); - memcpy(&new_gw->gw_addr, &gw->gw_addr, sizeof(new_gw->gw_addr)); - new_gw->dst_len = gw->dst_len; - new_gw->src_len = gw->src_len; - new_gw->metric = gw->metric; - new_gw->protocol = gw->protocol; - new_gw->scope = gw->scope; - new_gw->type = gw->type; - return new_gw; -} - -static void log_debug_gw(char *msg, struct pingu_gateway *gw) -{ - char destbuf[64], gwaddrbuf[64]; - log_debug("%s: %s/%i via %s metric %i", msg, - sockaddr_to_string(&gw->dest, destbuf, sizeof(destbuf)), - gw->dst_len, - sockaddr_to_string(&gw->gw_addr, gwaddrbuf, sizeof(gwaddrbuf)), - gw->metric); -} - -static int gateway_cmp(struct pingu_gateway *a, struct pingu_gateway *b) -{ - int r; - if (a->dst_len != b->dst_len) - return a->dst_len - b->dst_len; - r = sockaddr_cmp(&a->dest, &b->dest); - if (r != 0) - return r; - r = sockaddr_cmp(&a->gw_addr, &b->gw_addr); - if (r != 0) - return r; - return a->metric - b->metric; -} - -static struct pingu_gateway *pingu_gateway_get(struct list_head *gateway_list, - struct pingu_gateway *gw) -{ - struct pingu_gateway *entry; - list_for_each_entry(entry, gateway_list, gateway_list_entry) { - if (gateway_cmp(entry, gw) == 0) - return entry; - } - return NULL; -} - -void pingu_gateway_del_all(struct list_head *head) -{ - struct pingu_gateway *gw, *n; - list_for_each_entry_safe(gw, n, head, gateway_list_entry) { - list_del(&gw->gateway_list_entry); - free(gw); - } -} - -void pingu_gateway_add(struct list_head *gateway_list, - struct pingu_gateway *gw) -{ - struct pingu_gateway *new_gw = pingu_gateway_clone(gw); - if (new_gw == NULL) - return; - pingu_gateway_add_sorted(gateway_list, new_gw); -} - -void pingu_gateway_del(struct list_head *gateway_list, - struct pingu_gateway *delete) -{ - struct pingu_gateway *gw = pingu_gateway_get(gateway_list, delete); - if (gw == NULL) - return; - log_debug_gw("removed", gw); - list_del(&gw->gateway_list_entry); - free(gw); -} - -int is_default_gw(struct pingu_gateway *route) -{ - switch (route->dest.sa.sa_family) { - case AF_INET: - return ((route->dest.sin.sin_addr.s_addr == 0) - && (route->gw_addr.sin.sin_addr.s_addr != 0)); - break; - case AF_INET6: - log_debug("TODO: ipv6"); - break; - } - return 0; -} - -struct pingu_gateway *pingu_gateway_first_default(struct list_head *gateway_list) -{ - struct pingu_gateway *entry; - list_for_each_entry(entry, gateway_list, gateway_list_entry) { - if (is_default_gw(entry)) - return entry; - } - return NULL; -} diff --git a/pingu_gateway.h b/pingu_gateway.h deleted file mode 100644 index b2f424f..0000000 --- a/pingu_gateway.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef PINGU_GATEWAY_H -#define PINGU_GATEWAY_H - -#include "list.h" -#include "sockaddr_util.h" - -struct pingu_gateway { - union sockaddr_any gw_addr; - union sockaddr_any dest; - union sockaddr_any src; - unsigned char dst_len; - unsigned char src_len; - - int metric; - unsigned char protocol; - unsigned char scope; - unsigned char type; - struct list_head gateway_list_entry; -}; - -void pingu_gateway_del_all(struct list_head *head); -void pingu_gateway_add(struct list_head *gateway_list, - struct pingu_gateway *gw); -void pingu_gateway_del(struct list_head *gateway_list, - struct pingu_gateway *gw); -int is_default_gw(struct pingu_gateway *route); -struct pingu_gateway *pingu_gateway_first_default(struct list_head *gateway_list); - - -#endif diff --git a/pingu_iface.c b/pingu_iface.c index 6816041..5ae0317 100644 --- a/pingu_iface.c +++ b/pingu_iface.c @@ -118,7 +118,7 @@ struct pingu_iface *pingu_iface_get_by_name_or_new(const char *name) strlcpy(iface->name, name, sizeof(iface->name)); list_init(&iface->ping_list); - list_init(&iface->gateway_list); + list_init(&iface->route_list); list_add(&iface->iface_list_entry, &iface_list); return iface; } @@ -130,7 +130,7 @@ void pingu_iface_set_addr(struct pingu_iface *iface, int family, if (len <= 0 || data == NULL) { iface->has_address = 0; iface->has_binding = 0; - pingu_gateway_del_all(&iface->gateway_list); + pingu_route_del_all(&iface->route_list); log_debug("%s: address removed", iface->name); return; } @@ -147,10 +147,10 @@ void pingu_iface_set_balance(struct pingu_iface *iface, int balance_weight) } #if 0 -void pingu_gateway_dump(struct pingu_iface *iface) +void pingu_route_dump(struct pingu_iface *iface) { - struct pingu_gateway *gw; - list_for_each_entry(gw, &iface->gateway_list, gateway_list_entry) { + struct pingu_route *gw; + list_for_each_entry(gw, &iface->route_list, route_list_entry) { char buf[64]; sockaddr_to_string(&gw->gw_addr, buf, sizeof(buf)); log_debug("dump: %s: via %s metric %i", iface->name, buf, @@ -160,15 +160,15 @@ void pingu_gateway_dump(struct pingu_iface *iface) #endif void pingu_iface_gw_action(struct pingu_iface *iface, - struct pingu_gateway *gw, int action) + struct pingu_route *gw, int action) { switch (action) { case RTM_NEWROUTE: - pingu_gateway_add(&iface->gateway_list, gw); + pingu_route_add(&iface->route_list, gw); log_debug("%s: added route", iface->name); break; case RTM_DELROUTE: - pingu_gateway_del(&iface->gateway_list, gw); + pingu_route_del(&iface->route_list, gw); log_debug("%s: removed route", iface->name); break; } @@ -178,8 +178,8 @@ void pingu_iface_gw_action(struct pingu_iface *iface, void pingu_iface_update_routes(struct pingu_iface *iface, int action) { - struct pingu_gateway *route; - list_for_each_entry(route, &iface->gateway_list, gateway_list_entry) { + 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); } diff --git a/pingu_iface.h b/pingu_iface.h index 53e240e..14f8ba5 100644 --- a/pingu_iface.h +++ b/pingu_iface.h @@ -4,7 +4,7 @@ #include <netinet/in.h> #include <ev.h> -#include "pingu_gateway.h" +#include "pingu_route.h" #include "sockaddr_util.h" #include "list.h" @@ -25,7 +25,7 @@ struct pingu_iface { int route_table; struct list_head iface_list_entry; struct list_head ping_list; - struct list_head gateway_list; + struct list_head route_list; struct ev_io socket_watcher; }; @@ -41,7 +41,7 @@ void pingu_iface_set_addr(struct pingu_iface *iface, int family, void *data, int len); int pingu_iface_set_route_table(struct pingu_iface *iface, int table); void pingu_iface_gw_action(struct pingu_iface *iface, - struct pingu_gateway *gw, int action); + struct pingu_route *gw, int action); void pingu_iface_update_routes(struct pingu_iface *iface, int action); void pingu_iface_cleanup(void); diff --git a/pingu_netlink.c b/pingu_netlink.c index 5c6fba5..212e8e9 100644 --- a/pingu_netlink.c +++ b/pingu_netlink.c @@ -299,7 +299,7 @@ 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_gateway *route, + struct pingu_route *route, int iface_index, int table) { struct { @@ -339,7 +339,7 @@ int netlink_route_modify(struct netlink_fd *fd, int action_type, static int add_one_nh(struct rtattr *rta, struct rtnexthop *rtnh, struct pingu_iface *iface, - struct pingu_gateway *route) + struct pingu_route *route) { if (route == NULL) return 0; @@ -359,7 +359,7 @@ static int add_nexthops(struct nlmsghdr *nlh, size_t nlh_size, struct rtattr *rta = (void *)buf; struct rtnexthop *rtnh; struct pingu_iface *iface; - struct pingu_gateway *route; + struct pingu_route *route; struct pingu_host *host; int count = 0; @@ -369,7 +369,7 @@ static int add_nexthops(struct nlmsghdr *nlh, size_t nlh_size, rtnh = RTA_DATA(rta); list_for_each_entry(iface, iface_list, iface_list_entry) { - route = pingu_gateway_first_default(&iface->gateway_list); + route = pingu_route_first_default(&iface->route_list); switch (action_type) { case RTM_NEWROUTE: host = pingu_host_find_by_iface(iface); @@ -440,14 +440,14 @@ int netlink_route_multipath(struct netlink_fd *fd, int action_type, } int netlink_route_replace_or_add(struct netlink_fd *fd, - struct pingu_gateway *route, + struct pingu_route *route, int iface_index, int table) { return netlink_route_modify(fd, RTM_NEWROUTE, route, iface_index, table); } int netlink_route_delete(struct netlink_fd *fd, - struct pingu_gateway *route, + struct pingu_route *route, int iface_index, int table) { return netlink_route_modify(fd, RTM_DELROUTE, route, iface_index, table); @@ -455,9 +455,9 @@ int netlink_route_delete(struct netlink_fd *fd, static void netlink_route_flush(struct netlink_fd *fd, struct pingu_iface *iface) { - struct pingu_gateway *gw; + struct pingu_route *gw; int err; - list_for_each_entry(gw, &iface->gateway_list, gateway_list_entry) { + list_for_each_entry(gw, &iface->route_list, route_list_entry) { err = netlink_route_delete(fd, gw, iface->index, iface->route_table); if (err > 0) log_error("%s: Failed to clean up route in table %i: ", @@ -609,7 +609,7 @@ static void netlink_addr_del_cb(struct nlmsghdr *nlmsg) pingu_iface_set_addr(iface, 0, NULL, 0); } -static struct pingu_gateway *gw_from_rtmsg(struct pingu_gateway *gw, +static struct pingu_route *gw_from_rtmsg(struct pingu_route *gw, struct rtmsg *rtm, struct rtattr **rta) { @@ -635,7 +635,7 @@ static struct pingu_gateway *gw_from_rtmsg(struct pingu_gateway *gw, return gw; } -static void log_route_change(struct pingu_gateway *route, +static void log_route_change(struct pingu_route *route, char *ifname, int table, int action) { char deststr[64] = "", gwstr[64] = "", viastr[68] = ""; @@ -657,7 +657,7 @@ static void netlink_route_cb_action(struct nlmsghdr *msg, int action) struct rtmsg *rtm = NLMSG_DATA(msg); struct rtattr *rta[RTA_MAX+1]; - struct pingu_gateway route; + struct pingu_route route; int err = 0; /* ignore route changes that we made ourselves via talk_fd */ @@ -768,7 +768,7 @@ error: } -int kernel_route_modify(int action, struct pingu_gateway *route, +int kernel_route_modify(int action, struct pingu_route *route, struct pingu_iface *iface, int table) { log_route_change(route, iface->name, table, action); diff --git a/pingu_netlink.h b/pingu_netlink.h index be21b85..d65de1f 100644 --- a/pingu_netlink.h +++ b/pingu_netlink.h @@ -5,7 +5,7 @@ #include "pingu_iface.h" int kernel_init(struct ev_loop *loop); -int kernel_route_modify(int action, struct pingu_gateway *route, +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); void kernel_cleanup_iface_routes(struct pingu_iface *iface); diff --git a/pingu_route.c b/pingu_route.c new file mode 100644 index 0000000..efc8ad0 --- /dev/null +++ b/pingu_route.c @@ -0,0 +1,128 @@ + +#include <stdlib.h> +#include <string.h> + +#include "list.h" +#include "log.h" +#include "pingu_route.h" + +static void pingu_route_add_sorted(struct list_head *route_list, + struct pingu_route *new_gw) +{ + struct pingu_route *gw; + list_for_each_entry(gw, route_list, route_list_entry) { + if (gw->metric > new_gw->metric) { + list_add_tail(&new_gw->route_list_entry, + &gw->route_list_entry); + return; + } + } + list_add_tail(&new_gw->route_list_entry, route_list); +} + +static struct pingu_route *pingu_route_clone(struct pingu_route *gw) +{ + struct pingu_route *new_gw = calloc(1, sizeof(struct pingu_route)); + if (gw == NULL) { + log_perror("Failed to allocate gateway"); + return NULL; + } + /* copy the fields without overwriting the list entry */ + memcpy(&new_gw->dest, &gw->dest, sizeof(new_gw->dest)); + memcpy(&new_gw->gw_addr, &gw->gw_addr, sizeof(new_gw->gw_addr)); + new_gw->dst_len = gw->dst_len; + new_gw->src_len = gw->src_len; + new_gw->metric = gw->metric; + new_gw->protocol = gw->protocol; + new_gw->scope = gw->scope; + new_gw->type = gw->type; + return new_gw; +} + +static void log_debug_gw(char *msg, struct pingu_route *gw) +{ + char destbuf[64], gwaddrbuf[64]; + log_debug("%s: %s/%i via %s metric %i", msg, + sockaddr_to_string(&gw->dest, destbuf, sizeof(destbuf)), + gw->dst_len, + sockaddr_to_string(&gw->gw_addr, gwaddrbuf, sizeof(gwaddrbuf)), + gw->metric); +} + +static int gateway_cmp(struct pingu_route *a, struct pingu_route *b) +{ + int r; + if (a->dst_len != b->dst_len) + return a->dst_len - b->dst_len; + r = sockaddr_cmp(&a->dest, &b->dest); + if (r != 0) + return r; + r = sockaddr_cmp(&a->gw_addr, &b->gw_addr); + if (r != 0) + return r; + return a->metric - b->metric; +} + +static struct pingu_route *pingu_route_get(struct list_head *route_list, + struct pingu_route *gw) +{ + struct pingu_route *entry; + list_for_each_entry(entry, route_list, route_list_entry) { + if (gateway_cmp(entry, gw) == 0) + return entry; + } + return NULL; +} + +void pingu_route_del_all(struct list_head *head) +{ + struct pingu_route *gw, *n; + list_for_each_entry_safe(gw, n, head, route_list_entry) { + list_del(&gw->route_list_entry); + free(gw); + } +} + +void pingu_route_add(struct list_head *route_list, + struct pingu_route *gw) +{ + struct pingu_route *new_gw = pingu_route_clone(gw); + if (new_gw == NULL) + return; + pingu_route_add_sorted(route_list, new_gw); +} + +void pingu_route_del(struct list_head *route_list, + struct pingu_route *delete) +{ + struct pingu_route *gw = pingu_route_get(route_list, delete); + if (gw == NULL) + return; + log_debug_gw("removed", gw); + list_del(&gw->route_list_entry); + free(gw); +} + +int is_default_gw(struct pingu_route *route) +{ + switch (route->dest.sa.sa_family) { + case AF_INET: + return ((route->dest.sin.sin_addr.s_addr == 0) + && (route->gw_addr.sin.sin_addr.s_addr != 0)); + break; + case AF_INET6: + log_debug("TODO: ipv6"); + break; + } + return 0; +} + +struct pingu_route *pingu_route_first_default(struct list_head *route_list) +{ + struct pingu_route *entry; + list_for_each_entry(entry, route_list, route_list_entry) { + if (is_default_gw(entry)) + return entry; + } + return NULL; +} diff --git a/pingu_route.h b/pingu_route.h new file mode 100644 index 0000000..5badb10 --- /dev/null +++ b/pingu_route.h @@ -0,0 +1,30 @@ +#ifndef pingu_route_H +#define pingu_route_H + +#include "list.h" +#include "sockaddr_util.h" + +struct pingu_route { + union sockaddr_any gw_addr; + union sockaddr_any dest; + union sockaddr_any src; + unsigned char dst_len; + unsigned char src_len; + + int metric; + unsigned char protocol; + unsigned char scope; + unsigned char type; + struct list_head route_list_entry; +}; + +void pingu_route_del_all(struct list_head *head); +void pingu_route_add(struct list_head *route_list, + struct pingu_route *gw); +void pingu_route_del(struct list_head *route_list, + struct pingu_route *gw); +int is_default_gw(struct pingu_route *route); +struct pingu_route *pingu_route_first_default(struct list_head *route_list); + + +#endif |