thom311 / libnl

Netlink Library Suite
GNU Lesser General Public License v2.1
419 stars 311 forks source link

route: properly handle multiple kernel prefix routes with same dst #385

Open KanjiMonster opened 3 months ago

KanjiMonster commented 3 months ago

When configuring IP(v6) addresses on interfaces, the kernel will install appropriate prefix routes (except when using noprefixroute).

When configuring addresses from the same subnet on multiple interfaces, the kernel will happily configure multiple prefix routes. Most prominent example are per interface IPv6 link local fe80::/64 routes.

Currently libnl treats these routes as identical, and thus will only keep the newest one of the routes in the cache (as each additional one is treated as an update to the previous route).

Therefore we need to extend route_id_attrs_get() to properly treat these routes as different:

Also, only kernel may create these routes, attempts from userspace will be rejected when trying to add a second route for the same prefix.

ip route output:

$ ip r show table all
...
10.0.0.0/24 dev tun0 proto kernel scope link src 10.0.0.1
10.0.0.0/24 dev enp0s31f6 proto kernel scope link src 10.0.0.2
...
broadcast 10.0.0.255 dev tun0 table local proto kernel scope link src 10.0.0.1
broadcast 10.0.0.255 dev enp0s31f6 table local proto kernel scope link src 10.0.0.2
...
fe80::/64 dev tun0 proto kernel metric 256 pref medium
fe80::/64 dev enp0s31f6 proto kernel metric 1024 pref medium
...
multicast ff00::/8 dev enp0s31f6 table local proto kernel metric 256 pref medium
multicast ff00::/8 dev tun0 table local proto kernel metric 256 pref medium

$ ip r show table all | wc -l
37

Before:

$ ./src/nl-route-list
...
inet 10.0.0.0/24 table main type unicast via dev tun0
...
inet 10.0.0.255 table local type broadcast via dev tun0
...
inet6 fe80::/64 table main type unicast via dev tun0
inet6 fe80::/64 table main type unicast via dev enp0s31f6
...
inet6 ff00::/8 table local type multicast via dev enp0s31f6

$ ./src/nl-route-list | grep -v cache | wc -l
34

After:

$ ./src/nl-route-list
...
inet 10.0.0.0/24 table main type unicast via dev tun0
inet 10.0.0.0/24 table main type unicast via dev enp0s31f6
...
inet6 fe80::/64 table main type unicast via dev tun0
inet6 fe80::/64 table main type unicast via dev enp0s31f6
...
inet6 ff00::/8 table local type multicast via dev enp0s31f6
inet6 ff00::/8 table local type multicast via dev tun0

$ ./src/nl-route-list | grep -v cache | wc -l
37

(ip route doesn't show cache routes)