Permalink
Show file tree
Hide file tree
4 comments
on commit
sign in to comment.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Fix IPv6 routing loops
- Loading branch information
1 parent
4ee0c93
commit 24afe94
Showing
2 changed files
with
249 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| --- /dev/null | ||
| +++ b/package/network/ipv6/odhcp6c/patches/001-ra-align-ifindex-resolving.patch | ||
| @@ -0,0 +1,52 @@ | ||
| +From 2b6959dfe2095402e004b63d9aca9900c074abb6 Mon Sep 17 00:00:00 2001 | ||
| +From: Hans Dedecker <dedeckeh@gmail.com> | ||
| +Date: Wed, 6 Jan 2021 21:15:49 +0100 | ||
| +Subject: [PATCH] ra: align ifindex resolving | ||
| + | ||
| +Use ioctl SIOCGIFINDEX to resolve ifindex similar as in init_dhcpv6 | ||
| + | ||
| +Signed-off-by: Hans Dedecker <dedeckeh@gmail.com> | ||
| +--- | ||
| + src/ra.c | 10 +++++++--- | ||
| + 1 file changed, 7 insertions(+), 3 deletions(-) | ||
| + | ||
| +diff --git a/src/ra.c b/src/ra.c | ||
| +index 337c0bd..32a3097 100644 | ||
| +--- a/src/ra.c | ||
| ++++ b/src/ra.c | ||
| +@@ -27,6 +27,7 @@ | ||
| + | ||
| + #include <net/if.h> | ||
| + #include <arpa/inet.h> | ||
| ++#include <sys/ioctl.h> | ||
| + #include <sys/socket.h> | ||
| + #include <sys/types.h> | ||
| + #include <netinet/in.h> | ||
| +@@ -76,6 +77,8 @@ static void ra_send_rs(int signal __attribute__((unused))); | ||
| + int ra_init(const char *ifname, const struct in6_addr *ifid, | ||
| + unsigned int options, unsigned int holdoff_interval) | ||
| + { | ||
| ++ struct ifreq ifr; | ||
| ++ | ||
| + ra_options = options; | ||
| + ra_holdoff_interval = holdoff_interval; | ||
| + | ||
| +@@ -84,11 +87,12 @@ int ra_init(const char *ifname, const struct in6_addr *ifid, | ||
| + if (sock < 0) | ||
| + goto failure; | ||
| + | ||
| +- if_index = if_nametoindex(ifname); | ||
| +- if (!if_index) | ||
| ++ memset(&ifr, 0, sizeof(ifr)); | ||
| ++ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1); | ||
| ++ if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) | ||
| + goto failure; | ||
| + | ||
| +- strncpy(if_name, ifname, sizeof(if_name) - 1); | ||
| ++ if_index = ifr.ifr_ifindex; | ||
| + lladdr = *ifid; | ||
| + | ||
| + rtnl = socket(AF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_ROUTE); | ||
| +-- | ||
| +2.20.1 | ||
| + | ||
| --- /dev/null | ||
| +++ b/package/network/ipv6/odhcp6c/patches/002-ra-fix-routing-loop-ppp-links.patch | ||
| @@ -0,0 +1,60 @@ | ||
| +From 53f07e90b7f1da6977143a488dd5cb73a33b233b Mon Sep 17 00:00:00 2001 | ||
| +From: Hans Dedecker <dedeckeh@gmail.com> | ||
| +Date: Sat, 9 Jan 2021 21:17:48 +0100 | ||
| +Subject: [PATCH] ra: fix routing loop on point to point links | ||
| + | ||
| +For point-to-point links (e.g. PPP) don't create a link prefix route | ||
| +when receiving a prefix information option with the on-link flag set. | ||
| +Point-to-point links are non shared media and as such a destination | ||
| +IPv6 address cannot be on-link. | ||
| +If a link prefix route points to a point-to-point link it can trigger | ||
| +a routing loop if the destination IPv6 address belongs to the prefix. | ||
| +If such a packet is received and not directed to a local IPv6 address | ||
| +it will be routed to the point-to-point link due to the link prefix route; | ||
| +the upstream ISP router will route the IPv6 packet back due to the assigned | ||
| +prefix route creating a "ping pong" effect | ||
| + | ||
| +Signed-off-by: Hans Dedecker <dedeckeh@gmail.com> | ||
| +--- | ||
| + src/ra.c | 11 ++++++++++- | ||
| + 1 file changed, 10 insertions(+), 1 deletion(-) | ||
| + | ||
| +diff --git a/src/ra.c b/src/ra.c | ||
| +index 32a3097..4e6dd64 100644 | ||
| +--- a/src/ra.c | ||
| ++++ b/src/ra.c | ||
| +@@ -51,6 +51,7 @@ | ||
| + #include "ra.h" | ||
| + | ||
| + static bool nocarrier = false; | ||
| ++static bool ptp_link = false; | ||
| + | ||
| + static int sock = -1, rtnl = -1; | ||
| + static int if_index = 0; | ||
| +@@ -87,6 +88,13 @@ int ra_init(const char *ifname, const struct in6_addr *ifid, | ||
| + if (sock < 0) | ||
| + goto failure; | ||
| + | ||
| ++ memset(&ifr, 0, sizeof(ifr)); | ||
| ++ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1); | ||
| ++ if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) | ||
| ++ goto failure; | ||
| ++ | ||
| ++ ptp_link = !!(ifr.ifr_flags & IFF_POINTOPOINT); | ||
| ++ | ||
| + memset(&ifr, 0, sizeof(ifr)); | ||
| + strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1); | ||
| + if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) | ||
| +@@ -488,7 +496,8 @@ bool ra_process(void) | ||
| + || entry->valid < entry->preferred) | ||
| + continue; | ||
| + | ||
| +- if (pinfo->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) | ||
| ++ if ((pinfo->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) && | ||
| ++ !ptp_link) | ||
| + changed |= odhcp6c_update_entry(STATE_RA_ROUTE, entry, | ||
| + 7200, ra_holdoff_interval); | ||
| + | ||
| +-- | ||
| +2.20.1 | ||
| + |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| --- /dev/null | ||
| +++ b/package/network/config/netifd/patches/001-interface_ip-add-unreachable-route-offlink-address.patch | ||
| @@ -0,0 +1,128 @@ | ||
| +From c00c8335d6188daa326ecfe5a62da15a9b9987e1 Mon Sep 17 00:00:00 2001 | ||
| +From: Hans Dedecker <dedeckeh@gmail.com> | ||
| +Date: Sat, 9 Jan 2021 21:18:45 +0100 | ||
| +Subject: [PATCH] interface-ip: add unreachable route if address is offlink | ||
| + | ||
| +In order to avoid a routing loop add an unreachable route for the | ||
| +address prefix is the offlink flag is set for an address. | ||
| +This fixes a routing loop which is currently present on point-to-point | ||
| +links (e.g PPP) when the wan interface is assigned a globally unique | ||
| +prefix (e.g. 2001:db8:1:0::/64) from which an IPv6 address is picked | ||
| +and installed on the wan interface | ||
| +(e.g. 2001:db8:1:0:5054:ff:feab:d87c/64) | ||
| + | ||
| +The prefix route 2001:db8:1::/64 would be present in the routing table | ||
| +which will route any packet with as destination 2001:db8:1::/64 to the wan | ||
| +interface and would be routed back by the upstream router due to the | ||
| +wan interface due to the assigned global unique prefix. | ||
| +Besides not installing the prefix route 2001:db8:1::/64 on point-to-point links | ||
| +adding an unreachable route is required to avoid the routing loop. | ||
| + | ||
| +Signed-off-by: Hans Dedecker <dedeckeh@gmail.com> | ||
| +--- | ||
| + interface-ip.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ | ||
| + 1 file changed, 69 insertions(+) | ||
| + | ||
| +diff --git a/interface-ip.c b/interface-ip.c | ||
| +index 3768000..1444fbf 100644 | ||
| +--- a/interface-ip.c | ||
| ++++ b/interface-ip.c | ||
| +@@ -684,6 +684,22 @@ interface_update_proto_addr(struct vlist_tree *tree, | ||
| + if (!(a_old->flags & DEVADDR_EXTERNAL)) { | ||
| + interface_handle_subnet_route(iface, a_old, false); | ||
| + system_del_address(dev, a_old); | ||
| ++ | ||
| ++ if ((a_old->flags & DEVADDR_OFFLINK) && (a_old->mask < (v6 ? 128 : 32))) { | ||
| ++ struct device_route route; | ||
| ++ | ||
| ++ memset(&route, 0, sizeof(route)); | ||
| ++ route.flags = v6 ? DEVADDR_INET6 : DEVADDR_INET4; | ||
| ++ route.metric = INT32_MAX; | ||
| ++ route.mask = a_old->mask; | ||
| ++ route.addr = a_old->addr; | ||
| ++ | ||
| ++ clear_if_addr(&route.addr, route.mask); | ||
| ++ | ||
| ++ /* Delete null-route */ | ||
| ++ system_del_route(NULL, &route); | ||
| ++ } | ||
| ++ | ||
| + } | ||
| + } | ||
| + free(a_old->pclass); | ||
| +@@ -708,6 +724,26 @@ interface_update_proto_addr(struct vlist_tree *tree, | ||
| + } | ||
| + | ||
| + if (!keep) { | ||
| ++ if (!(a_new->flags & DEVADDR_EXTERNAL) && | ||
| ++ (a_new->flags & DEVADDR_OFFLINK) && | ||
| ++ (a_new->mask < (v6 ? 128 : 32))) { | ||
| ++ struct device_route route; | ||
| ++ | ||
| ++ memset(&route, 0, sizeof(route)); | ||
| ++ route.flags = v6 ? DEVADDR_INET6 : DEVADDR_INET4; | ||
| ++ route.metric = INT32_MAX; | ||
| ++ route.mask = a_new->mask; | ||
| ++ route.addr = a_new->addr; | ||
| ++ | ||
| ++ clear_if_addr(&route.addr, route.mask); | ||
| ++ | ||
| ++ /* | ||
| ++ * In case off link is specifed as address property | ||
| ++ * add null-route to avoid routing loops | ||
| ++ */ | ||
| ++ system_add_route(NULL, &route); | ||
| ++ } | ||
| ++ | ||
| + if (a_new->policy_table) | ||
| + interface_add_addr_rules(a_new, true); | ||
| + } | ||
| +@@ -1578,12 +1614,45 @@ void interface_ip_set_enabled(struct interface_ip_settings *ip, bool enabled) | ||
| + if (iface->metric || addr->policy_table) | ||
| + interface_handle_subnet_route(iface, addr, true); | ||
| + | ||
| ++ if ((addr->flags & DEVADDR_OFFLINK) && (addr->mask < (v6 ? 128 : 32))) { | ||
| ++ struct device_route route; | ||
| ++ | ||
| ++ memset(&route, 0, sizeof(route)); | ||
| ++ route.flags = v6 ? DEVADDR_INET6 : DEVADDR_INET4; | ||
| ++ route.metric = INT32_MAX; | ||
| ++ route.mask = addr->mask; | ||
| ++ route.addr = addr->addr; | ||
| ++ | ||
| ++ clear_if_addr(&route.addr, route.mask); | ||
| ++ | ||
| ++ /* | ||
| ++ * In case off link is specifed as address property | ||
| ++ * add null-route to avoid routing loops | ||
| ++ */ | ||
| ++ system_add_route(NULL, &route); | ||
| ++ } | ||
| ++ | ||
| + if (addr->policy_table) | ||
| + interface_add_addr_rules(addr, true); | ||
| + } else { | ||
| + interface_handle_subnet_route(iface, addr, false); | ||
| + system_del_address(dev, addr); | ||
| + | ||
| ++ if ((addr->flags & DEVADDR_OFFLINK) && (addr->mask < (v6 ? 128 : 32))) { | ||
| ++ struct device_route route; | ||
| ++ | ||
| ++ memset(&route, 0, sizeof(route)); | ||
| ++ route.flags = v6 ? DEVADDR_INET6 : DEVADDR_INET4; | ||
| ++ route.metric = INT32_MAX; | ||
| ++ route.mask = addr->mask; | ||
| ++ route.addr = addr->addr; | ||
| ++ | ||
| ++ clear_if_addr(&route.addr, route.mask); | ||
| ++ | ||
| ++ /* Delete null-route */ | ||
| ++ system_del_route(NULL, &route); | ||
| ++ } | ||
| ++ | ||
| + if (addr->policy_table) | ||
| + interface_add_addr_rules(addr, false); | ||
| + } | ||
| +-- | ||
| +2.20.1 | ||
| + |
24afe94There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed openwrt/openwrt@250dbb3 openwrt/openwrt@9999c87
24afe94There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I will wait a bit longer to see if I can get the dnsmasq fixes (and the fixes to the fixes) in one go :)
24afe94There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm waiting too :)
24afe94There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've picked up the latest fixes for both issues now in Master. I note that you may have already done this in your fork from a forum post?
Anyway, available if you need it.