mirror of
				https://github.com/systemd/systemd-stable.git
				synced 2025-10-30 20:25:01 +03:00 
			
		
		
		
	network: dhcp4: ignore gateway in static routes if destination is link-local or in the same network
This also configures routes to gateways in static routes if the destination is not in the same network.
This commit is contained in:
		| @@ -143,19 +143,6 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li | ||||
|         return 1; | ||||
| } | ||||
|  | ||||
| static int route_scope_from_address(const Route *route, const struct in_addr *self_addr) { | ||||
|         assert(route); | ||||
|         assert(self_addr); | ||||
|  | ||||
|         if (in4_addr_is_localhost(&route->dst.in) || | ||||
|             (in4_addr_is_set(self_addr) && in4_addr_equal(&route->dst.in, self_addr))) | ||||
|                 return RT_SCOPE_HOST; | ||||
|         else if (in4_addr_is_null(&route->gw.in)) | ||||
|                 return RT_SCOPE_LINK; | ||||
|         else | ||||
|                 return RT_SCOPE_UNIVERSE; | ||||
| } | ||||
|  | ||||
| static int dhcp_route_configure(Route *route, Link *link) { | ||||
|         Route *ret; | ||||
|         int r; | ||||
| @@ -250,11 +237,95 @@ static int link_set_dhcp_route_to_gateway(Link *link, const struct in_addr *gw) | ||||
|         return dhcp_route_configure(route, link); | ||||
| } | ||||
|  | ||||
| static int dhcp_route_configure_auto( | ||||
|                 Route *route, | ||||
|                 Link *link, | ||||
|                 const struct in_addr *gw) { | ||||
|  | ||||
|         struct in_addr address, netmask, prefix; | ||||
|         uint8_t prefixlen; | ||||
|         int r; | ||||
|  | ||||
|         assert(route); | ||||
|         assert(link); | ||||
|         assert(link->dhcp_lease); | ||||
|         assert(gw); | ||||
|  | ||||
|         /* The route object may be reused in an iteration. All elements must be set or cleared. */ | ||||
|  | ||||
|         r = sd_dhcp_lease_get_address(link->dhcp_lease, &address); | ||||
|         if (r < 0) | ||||
|                 return r; | ||||
|  | ||||
|         r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask); | ||||
|         if (r < 0) | ||||
|                 return r; | ||||
|  | ||||
|         prefix.s_addr = address.s_addr & netmask.s_addr; | ||||
|         prefixlen = in4_addr_netmask_to_prefixlen(&netmask); | ||||
|  | ||||
|         if (in4_addr_is_localhost(&route->dst.in)) { | ||||
|                 if (in4_addr_is_set(gw)) | ||||
|                         log_link_debug(link, "DHCP: requested route destination "IPV4_ADDRESS_FMT_STR"/%u is localhost, " | ||||
|                                        "ignoring gateway address "IPV4_ADDRESS_FMT_STR, | ||||
|                                        IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen, IPV4_ADDRESS_FMT_VAL(*gw)); | ||||
|  | ||||
|                 route->scope = RT_SCOPE_HOST; | ||||
|                 route->gw_family = AF_UNSPEC; | ||||
|                 route->gw = IN_ADDR_NULL; | ||||
|                 route->prefsrc = IN_ADDR_NULL; | ||||
|  | ||||
|         } else if (in4_addr_equal(&route->dst.in, &address)) { | ||||
|                 if (in4_addr_is_set(gw)) | ||||
|                         log_link_debug(link, "DHCP: requested route destination "IPV4_ADDRESS_FMT_STR"/%u is equivalent to the acquired address, " | ||||
|                                        "ignoring gateway address "IPV4_ADDRESS_FMT_STR, | ||||
|                                        IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen, IPV4_ADDRESS_FMT_VAL(*gw)); | ||||
|  | ||||
|                 route->scope = RT_SCOPE_HOST; | ||||
|                 route->gw_family = AF_UNSPEC; | ||||
|                 route->gw = IN_ADDR_NULL; | ||||
|                 route->prefsrc.in = address; | ||||
|  | ||||
|         } else if (route->dst_prefixlen >= prefixlen && | ||||
|                    (route->dst.in.s_addr & netmask.s_addr) == prefix.s_addr) { | ||||
|                 if (in4_addr_is_set(gw)) | ||||
|                         log_link_debug(link, "DHCP: requested route destination "IPV4_ADDRESS_FMT_STR"/%u is in the assigned network " | ||||
|                                        IPV4_ADDRESS_FMT_STR"/%u, ignoring gateway address "IPV4_ADDRESS_FMT_STR, | ||||
|                                        IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen, | ||||
|                                        IPV4_ADDRESS_FMT_VAL(prefix), prefixlen, | ||||
|                                        IPV4_ADDRESS_FMT_VAL(*gw)); | ||||
|  | ||||
|                 route->scope = RT_SCOPE_LINK; | ||||
|                 route->gw_family = AF_UNSPEC; | ||||
|                 route->gw = IN_ADDR_NULL; | ||||
|                 route->prefsrc.in = address; | ||||
|  | ||||
|         } else { | ||||
|                 if (in4_addr_is_null(gw)) { | ||||
|                         log_link_debug(link, "DHCP: requested route destination "IPV4_ADDRESS_FMT_STR"/%u is not in the assigned network " | ||||
|                                        IPV4_ADDRESS_FMT_STR"/%u, but no gateway is specified, ignoring.", | ||||
|                                        IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen, | ||||
|                                        IPV4_ADDRESS_FMT_VAL(prefix), prefixlen); | ||||
|                         return 0; | ||||
|                 } | ||||
|  | ||||
|                 r = link_set_dhcp_route_to_gateway(link, gw); | ||||
|                 if (r < 0) | ||||
|                         return r; | ||||
|  | ||||
|                 route->scope = RT_SCOPE_UNIVERSE; | ||||
|                 route->gw_family = AF_INET; | ||||
|                 route->gw.in = *gw; | ||||
|                 route->prefsrc.in = address; | ||||
|         } | ||||
|  | ||||
|         return dhcp_route_configure(route, link); | ||||
| } | ||||
|  | ||||
| static int link_set_dhcp_static_routes(Link *link) { | ||||
|         _cleanup_free_ sd_dhcp_route **static_routes = NULL; | ||||
|         bool classless_route = false, static_route = false; | ||||
|         _cleanup_(route_freep) Route *route = NULL; | ||||
|         struct in_addr address; | ||||
|         int n, r; | ||||
|  | ||||
|         assert(link); | ||||
| @@ -263,10 +334,6 @@ static int link_set_dhcp_static_routes(Link *link) { | ||||
|         if (!link->network->dhcp_use_routes) | ||||
|                 return 0; | ||||
|  | ||||
|         r = sd_dhcp_lease_get_address(link->dhcp_lease, &address); | ||||
|         if (r < 0) | ||||
|                 return r; | ||||
|  | ||||
|         n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes); | ||||
|         if (IN_SET(n, 0, -ENODATA)) { | ||||
|                 log_link_debug(link, "DHCP: No static routes received from DHCP server."); | ||||
| @@ -303,11 +370,13 @@ static int link_set_dhcp_static_routes(Link *link) { | ||||
|         route->mtu = link->network->dhcp_route_mtu; | ||||
|  | ||||
|         for (int i = 0; i < n; i++) { | ||||
|                 struct in_addr gw; | ||||
|  | ||||
|                 if (sd_dhcp_route_get_option(static_routes[i]) != | ||||
|                     (classless_route ? SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE : SD_DHCP_OPTION_STATIC_ROUTE)) | ||||
|                         continue; | ||||
|  | ||||
|                 r = sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in); | ||||
|                 r = sd_dhcp_route_get_gateway(static_routes[i], &gw); | ||||
|                 if (r < 0) | ||||
|                         return r; | ||||
|  | ||||
| @@ -319,13 +388,7 @@ static int link_set_dhcp_static_routes(Link *link) { | ||||
|                 if (r < 0) | ||||
|                         return r; | ||||
|  | ||||
|                 route->scope = route_scope_from_address(route, &address); | ||||
|                 if (IN_SET(route->scope, RT_SCOPE_LINK, RT_SCOPE_UNIVERSE)) | ||||
|                         route->prefsrc.in = address; | ||||
|                 else | ||||
|                         route->prefsrc = IN_ADDR_NULL; | ||||
|  | ||||
|                 r = dhcp_route_configure(route, link); | ||||
|                 r = dhcp_route_configure_auto(route, link, &gw); | ||||
|                 if (r < 0) | ||||
|                         return r; | ||||
|         } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user