summaryrefslogtreecommitdiff
path: root/proto/static/static.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto/static/static.c')
-rw-r--r--proto/static/static.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/proto/static/static.c b/proto/static/static.c
index 9308c59a..6b42a379 100644
--- a/proto/static/static.c
+++ b/proto/static/static.c
@@ -218,15 +218,18 @@ static_init(struct proto_config *c)
return p;
}
-static int
-static_same_route(struct static_route *x, struct static_route *y)
+static inline int
+static_same_net(struct static_route *x, struct static_route *y)
{
- return ipa_equal(x->net, y->net)
- && x->masklen == y->masklen
- && x->dest == y->dest
+ return ipa_equal(x->net, y->net) && (x->masklen == y->masklen);
+}
+
+static inline int
+static_same_dest(struct static_route *x, struct static_route *y)
+{
+ return (x->dest == y->dest)
&& (x->dest != RTD_ROUTER || ipa_equal(x->via, y->via))
- && (x->dest != RTD_DEVICE || !strcmp(x->if_name, y->if_name))
- ;
+ && (x->dest != RTD_DEVICE || !strcmp(x->if_name, y->if_name));
}
static void
@@ -234,18 +237,25 @@ static_match(struct proto *p, struct static_route *r, struct static_config *n)
{
struct static_route *t;
+ /*
+ * For given old route *r we find whether a route to the same
+ * network is also in the new route list. In that case, we keep the
+ * route and possibly update the route later if destination changed.
+ * Otherwise, we remove the route.
+ */
+
if (r->neigh)
r->neigh->data = NULL;
WALK_LIST(t, n->iface_routes)
- if (static_same_route(r, t))
+ if (static_same_net(r, t))
{
- t->installed = 1;
+ t->installed = static_same_dest(r, t);
return;
}
WALK_LIST(t, n->other_routes)
- if (static_same_route(r, t))
+ if (static_same_net(r, t))
{
- t->installed = 1;
+ t->installed = static_same_dest(r, t);
return;
}
static_remove(p, r);