From aa424fea98fed25b3db5550738a01d53f534f177 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Tue, 2 Aug 2011 14:37:17 +0200 Subject: pingu: use source address for ip rule and copy scope link route --- pingu_iface.c | 12 ++++++++---- pingu_iface.h | 8 +++++++- pingu_netlink.c | 41 +++++++++++++++++++++++++++-------------- 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/pingu_iface.c b/pingu_iface.c index 78d8e9a..6a87a24 100644 --- a/pingu_iface.c +++ b/pingu_iface.c @@ -171,8 +171,12 @@ struct pingu_gateway *pingu_gateway_clone(struct pingu_gateway *gw) /* 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->dest_len = gw->dest_len; + new_gw->protocol = gw->protocol; + new_gw->scope = gw->scope; + new_gw->type = gw->type; return new_gw; } @@ -181,7 +185,7 @@ 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->dest_len, + gw->dst_len, sockaddr_to_string(&gw->gw_addr, gwaddrbuf, sizeof(gwaddrbuf)), gw->metric); } @@ -189,8 +193,8 @@ static void log_debug_gw(char *msg, struct pingu_gateway *gw) static int gateway_cmp(struct pingu_gateway *a, struct pingu_gateway *b) { int r; - if (a->dest_len != b->dest_len) - return a->dest_len - b->dest_len; + 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; diff --git a/pingu_iface.h b/pingu_iface.h index 14aab04..d3a4988 100644 --- a/pingu_iface.h +++ b/pingu_iface.h @@ -10,8 +10,14 @@ struct pingu_gateway { union sockaddr_any gw_addr; union sockaddr_any dest; - int dest_len; + 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; }; diff --git a/pingu_netlink.c b/pingu_netlink.c index e16c2d0..709e00c 100644 --- a/pingu_netlink.c +++ b/pingu_netlink.c @@ -223,10 +223,10 @@ int netlink_route_modify(struct netlink_fd *fd, int action_type, req.msg.rtm_family = route->dest.sa.sa_family; req.msg.rtm_table = table; - req.msg.rtm_dst_len = route->dest_len; - req.msg.rtm_protocol = RTPROT_BOOT; - req.msg.rtm_scope = RT_SCOPE_UNIVERSE; - req.msg.rtm_type = RTN_UNICAST; + req.msg.rtm_dst_len = route->dst_len; + req.msg.rtm_protocol = route->protocol; + req.msg.rtm_scope = route->scope; + req.msg.rtm_type = route->type; netlink_add_rtattr_addr_any(&req.nlh, sizeof(req), RTA_DST, &route->dest); @@ -266,6 +266,7 @@ int netlink_rule_modify(struct netlink_fd *fd, struct sockaddr_nl addr; // uint32_t preference = 1000; // in_addr_t destination = 0; + char buf[64]; memset(&req, 0, sizeof(req)); memset(&addr, 0, sizeof(addr)); @@ -284,8 +285,12 @@ int netlink_rule_modify(struct netlink_fd *fd, req.msg.rtm_type = RTN_UNICAST; // netlink_add_rtattr_l(&req.nlh, sizeof(req), FRA_PRIORITY, &preference, 4); -// netlink_add_rtattr_l(&req.nlh, sizeof(req), FRA_SRC, &destination, 4); - netlink_add_rtattr_l(&req.nlh, sizeof(req), FRA_OIFNAME, iface->name, strlen(iface->name)+1); + + req.msg.rtm_src_len = 32; + netlink_add_rtattr_addr_any(&req.nlh, sizeof(req), FRA_SRC, + &iface->primary_addr); + sockaddr_to_string(&iface->primary_addr, buf, sizeof(buf)); +// netlink_add_rtattr_l(&req.nlh, sizeof(req), FRA_OIFNAME, iface->name, strlen(iface->name)+1); return sendto(fd->fd, (void *) &req, sizeof(req), 0, (struct sockaddr *) &addr, sizeof(addr)); @@ -330,7 +335,6 @@ static void netlink_link_new_cb(struct nlmsghdr *msg) iface->index = ifi->ifi_index; iface->has_link = 1; pingu_iface_bind_socket(iface, 1); - netlink_rule_replace_or_add(&talk_fd, iface); } static void netlink_link_del_cb(struct nlmsghdr *msg) @@ -352,7 +356,6 @@ static void netlink_link_del_cb(struct nlmsghdr *msg) log_info("Interface '%s' deleted", ifname); iface->index = 0; iface->has_link = 0; - netlink_rule_del(&talk_fd, iface); } static void netlink_addr_new_cb(struct nlmsghdr *msg) @@ -375,6 +378,7 @@ static void netlink_addr_new_cb(struct nlmsghdr *msg) pingu_iface_set_addr(iface, ifa->ifa_family, RTA_DATA(rta[IFA_LOCAL]), RTA_PAYLOAD(rta[IFA_LOCAL])); + netlink_rule_replace_or_add(&talk_fd, iface); } static void netlink_addr_del_cb(struct nlmsghdr *nlmsg) @@ -394,7 +398,8 @@ static void netlink_addr_del_cb(struct nlmsghdr *nlmsg) if (iface == NULL) return; - pingu_iface_set_addr(iface, 0, NULL, 0); + pingu_iface_set_addr(iface, 0, NULL, 0); + netlink_rule_del(&talk_fd, iface); } static struct pingu_gateway *gw_from_rtmsg(struct pingu_gateway *gw, @@ -402,8 +407,16 @@ static struct pingu_gateway *gw_from_rtmsg(struct pingu_gateway *gw, struct rtattr **rta) { memset(gw, 0, sizeof(*gw)); - gw->dest_len = rtm->rtm_dst_len; + gw->dst_len = rtm->rtm_dst_len; + gw->src_len = rtm->rtm_src_len; gw->dest.sa.sa_family = rtm->rtm_family; + gw->protocol = rtm->rtm_protocol; + gw->scope = rtm->rtm_scope; + gw->type = rtm->rtm_type; + + if (rta[RTA_SRC] != NULL) + sockaddr_init(&gw->src, rtm->rtm_family, RTA_DATA(rta[RTA_SRC])); + if (rta[RTA_DST] != NULL) sockaddr_init(&gw->dest, rtm->rtm_family, RTA_DATA(rta[RTA_DST])); @@ -425,8 +438,8 @@ static void log_route_change(struct pingu_gateway *route, sockaddr_to_string(&route->dest, deststr, sizeof(deststr)); sockaddr_to_string(&route->gw_addr, gwstr, sizeof(gwstr)); - log_debug("%s route to %s via %s dev %s table %i", actionstr, - deststr, gwstr, ifname, table); + log_debug("%s route to %s/%i via %s dev %s table %i", actionstr, + deststr, route->dst_len, gwstr, ifname, table); } static int is_default_gw(struct pingu_gateway *route) @@ -456,8 +469,8 @@ static void netlink_route_cb_action(struct nlmsghdr *msg, int action) return; netlink_parse_rtattr(rta, RTA_MAX, RTM_RTA(rtm), RTM_PAYLOAD(msg)); - if (rta[RTA_OIF] == NULL || rta[RTA_GATEWAY] == NULL - || rtm->rtm_family != PF_INET || rtm->rtm_table != RT_TABLE_MAIN) + if (rta[RTA_OIF] == NULL || rtm->rtm_family != PF_INET + || rtm->rtm_table != RT_TABLE_MAIN) return; gw_from_rtmsg(&route, rtm, rta); -- cgit v1.2.3