mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-01 02:08:02 +02:00
ndisc: Accept routes from on-link prefixes form ra
It is possible that an ra leads to two routes having
the same prefix as well as the same prefix length.
One of them, however, refers to the on-link prefix,
and the other one to a route from the route information field.
(Moreover, they might have different route preferences.)
Hence, if both routes differ in the on-link property,
both are added, and the route from the route information
option receives a metric penalty.
Fixed #1163.
(cherry picked from commit 11832e2ba3)
This commit is contained in:
parent
093bbd0fcf
commit
02c3f7c946
3 changed files with 53 additions and 4 deletions
|
|
@ -211,6 +211,7 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
const NMNDiscRoute route = {
|
||||
.network = r_network,
|
||||
.plen = r_plen,
|
||||
.on_link = TRUE,
|
||||
.expiry_msec =
|
||||
_nm_ndisc_lifetime_to_expiry(now_msec,
|
||||
ndp_msg_opt_prefix_valid_time(msg, offset)),
|
||||
|
|
@ -249,6 +250,7 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
.network = network,
|
||||
.gateway = gateway_addr,
|
||||
.plen = plen,
|
||||
.on_link = FALSE,
|
||||
.expiry_msec =
|
||||
_nm_ndisc_lifetime_to_expiry(now_msec, ndp_msg_opt_route_lifetime(msg, offset)),
|
||||
.preference = _route_preference_coerce(ndp_msg_opt_route_preference(msg, offset)),
|
||||
|
|
|
|||
|
|
@ -161,8 +161,9 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex *multi_idx,
|
|||
.table_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
.metric_any = TRUE,
|
||||
.metric = 0,
|
||||
.rt_pref = ndisc_route->preference,
|
||||
/* Non-on_link routes get a small penalty */
|
||||
.metric = ndisc_route->duplicate && !ndisc_route->on_link ? 5 : 0,
|
||||
.rt_pref = ndisc_route->preference,
|
||||
};
|
||||
nm_assert((NMIcmpv6RouterPref) r.rt_pref == ndisc_route->preference);
|
||||
|
||||
|
|
@ -349,12 +350,47 @@ _ASSERT_data_gateways(const NMNDiscDataInternal *data)
|
|||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static bool
|
||||
is_duplicate_route(const NMNDiscRoute *r0, const NMNDiscRoute *r1)
|
||||
{
|
||||
return IN6_ARE_ADDR_EQUAL(&r0->network, &r1->network) && r0->plen == r1->plen;
|
||||
}
|
||||
|
||||
static void
|
||||
_data_complete_prepare_routes(GArray *routes)
|
||||
{
|
||||
guint i, j;
|
||||
|
||||
for (i = 0; i < routes->len; i++) {
|
||||
NMNDiscRoute *r0 = &nm_g_array_index(routes, NMNDiscRoute, i);
|
||||
|
||||
r0->duplicate = FALSE;
|
||||
}
|
||||
for (i = 0; i < routes->len; i++) {
|
||||
NMNDiscRoute *r0 = &nm_g_array_index(routes, NMNDiscRoute, i);
|
||||
|
||||
for (j = i + 1; j < routes->len; j++) {
|
||||
NMNDiscRoute *r1 = &nm_g_array_index(routes, NMNDiscRoute, j);
|
||||
|
||||
if (!is_duplicate_route(r0, r1))
|
||||
continue;
|
||||
|
||||
r0->duplicate = TRUE;
|
||||
r1->duplicate = TRUE;
|
||||
|
||||
/* Maybe after index j, there is yet another duplicate. But we
|
||||
* will find that later, when i becomes j. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const NMNDiscData *
|
||||
_data_complete(NMNDiscDataInternal *data)
|
||||
{
|
||||
_ASSERT_data_gateways(data);
|
||||
|
||||
_data_complete_prepare_routes(data->routes);
|
||||
#define _SET(data, field) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
|
|
@ -658,8 +694,17 @@ nm_ndisc_add_route(NMNDisc *ndisc, const NMNDiscRoute *new_item, gint64 now_msec
|
|||
for (i = 0; i < rdata->routes->len;) {
|
||||
NMNDiscRoute *item = &nm_g_array_index(rdata->routes, NMNDiscRoute, i);
|
||||
|
||||
if (IN6_ARE_ADDR_EQUAL(&item->network, &new_item->network)
|
||||
&& item->plen == new_item->plen) {
|
||||
/*
|
||||
* It is possible that two entries in rdata->routes have
|
||||
* the same prefix as well as the same prefix length.
|
||||
* One of them, however, refers to the on-link prefix,
|
||||
* and the other one to a route from the route information field.
|
||||
* Moreover, they might have different route preferences.
|
||||
* Hence, if both routes differ in the on-link flag,
|
||||
* comparison is aborted, and both routes are added.
|
||||
*/
|
||||
if (IN6_ARE_ADDR_EQUAL(&item->network, &new_item->network) && item->plen == new_item->plen
|
||||
&& item->on_link == new_item->on_link) {
|
||||
if (new_item->expiry_msec <= now_msec) {
|
||||
g_array_remove_index(rdata->routes, i);
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -115,6 +115,8 @@ typedef struct _NMNDiscRoute {
|
|||
gint64 expiry_msec;
|
||||
NMIcmpv6RouterPref preference;
|
||||
guint8 plen;
|
||||
bool on_link : 1;
|
||||
bool duplicate : 1;
|
||||
} NMNDiscRoute;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue