Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dhcpcd not ignoring source-based routes on linux #372

Merged
merged 1 commit into from
Oct 29, 2024

Conversation

sshambar
Copy link
Contributor

I'm using ipv6 source-based routing on a machine with multiple WANs. I'm adding routes for each delegated subnet to their respective WAN interface, eg:

# ip -6 route show
default from <DELEGATED-SUBNET> via <GATEWAY> dev <WAN-DEV> ...

However, dhcpcd on the WAN doesn't parse the RTA_SRC route attribute, so it adds the route to it's internal kernel route list as the "default route" - the net effect being that if the upstream router removes and adds back the real default route (eg. ISP goes down momentarily), dhcpcd will think these source-routes are existing kernel default routes, and won't add the new default route back.

This simple pull request patches if-linux.c to parse the RTA_SRC attribute for a "specified" route and ignores the route, after which dhcpcd behaves correctly.

I haven't modified the code for other platforms as I'm not sure how/if they support source-based routing :)

Please feel free to use a totally different method to exclude source routes if you feel this is "kludgy"...

src/if-linux.c Outdated Show resolved Hide resolved
@rsmarples
Copy link
Member

RTA_SRC is just a hint for the address selection algo used by the kernel. It doesn't make the route any more special.
From the example you posted, it sure looks to me like a default route?

Can you post a real world example, maybe with your routes and dhcpcd's default route and highlight which one is from dhcpcd please?

@sshambar
Copy link
Contributor Author

sshambar commented Oct 8, 2024

RTA_SRC is just a hint for the address selection algo used by the kernel. It doesn't make the route any more special. From the example you posted, it sure looks to me like a default route?

I believe the "hint" is RTA_PREFSRC. RTA_SRC is part of the route itself, and is generally ::0/0 (or "default" in ip route lingo)

Can you post a real world example, maybe with your routes and dhcpcd's default route and highlight which one is from dhcpcd please?

# Adds a traditional default route, RTA_SRC is ::0/0
$ ip -6 route add default via <LLADDR> dev <DEV>
# Adds a source-based default route, RTA_SRC is <SUBNET>
$ ip -6 route add default from <SUBNET> via <LLADDR> dev <DEV>
# Adds traditional default route with "hint" (RTA_SRC is ::0/0, RTA_PREFSRC is <GADDR>)
$ ip -6 route add default via <LLADDR> dev <DEV> src <GADDR>

# To show routes under dhcpcd on vlan1 in a test network (w/ src route added):
$ ip -6 route show default # <- will show both default routes
default from fd55:5555:5555:c020::/60 via fe80::5375:19b4:8204:362a dev vlan1 metric 99 pref medium
default via fe80::5375:19b4:8204:362a dev vlan1 proto ra metric 1000 pref medium
$ ip -6 route show default from default # <- will show only the non-source default route
default via fe80::5375:19b4:8204:362a dev vlan1 proto ra metric 1000 pref medium

Source-based routing is basically the same as adding an ip rule from <SUBNET>... but makes it possible to scope the default routes in the "main" table (since dhcpcd doesn't currently support using routing tables -- for policy routing).

Let me know if that doesn't answer your question...
S.

PS As an aside, I just tested with ip route add default via <LLADDR> dev <DEV> src <GADDR> metric <NOT-DEAULT-ROUTE-METRIC> -- and then deleted it -- and dhcpcd also removed it's internal default route... so ideally it's internal table should include the route metric in it's "primary key" (as the linux kernel does), so that routes that it doesn't manage don't cause problems... but that's another kind of bug :)

src/if-linux.c Outdated
@@ -686,6 +686,22 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct nlmsghdr *nlm)
case RTA_DST:
sa = &rt->rt_dest;
break;
case RTA_SRC:
{
struct sockaddr ssa;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

struct sockaddr won't hold an INET6 address.
We have the sa_ss union to help with this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lol, my bad, been a few decades since I did socket programming in C, forgot how weird it can be :)

src/if-linux.c Outdated
salen = sa_addrlen(&ssa);
memcpy((char *)&ssa + sa_addroffset(&ssa),
RTA_DATA(rta), MIN(salen, RTA_PAYLOAD(rta)));
/* if source-route, ignore it */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we expand on this comment to say that "source routing can conflict with dhcpcd's notion of routing, so ignore for now." I feel that a simple comment may cause someone like me to read this in a few years and say "heh it works" but I've lost the context for why we want to ignore it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a more detailed comment, let me know if it's clear enough...

@rsmarples
Copy link
Member

Thanks for the summary. Can we put part of the in a comment in the code please just to clarify it? The one liner is not verbose enough as to why we are ignoring it.

Since source-based routes aren't used by dhcpcd, it's best if they
are ignored so that they aren't confused with default routes.
@sshambar
Copy link
Contributor Author

@rsmarples Just curious, I fixed the two issues from your review a couple weeks ago, was there something else you wanted me to change?

@sshambar sshambar requested a review from rsmarples October 26, 2024 22:24
@rsmarples
Copy link
Member

Sorry, I've been distracted of late.

@rsmarples rsmarples merged commit fa4e1dd into NetworkConfiguration:master Oct 29, 2024
2 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants