diff --git a/proto/static/static.c b/proto/static/static.c index 9b115acd..d3a595d3 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -62,7 +62,7 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa) rta a, *aa; rte *e; - if (r->installed) + if (r->installed > 0) return; DBG("Installing static route %I/%d, rtd=%d\n", r->net, r->masklen, r->dest); @@ -125,7 +125,7 @@ static_remove(struct proto *p, struct static_route *r) if (!r->installed) return; - DBG("Removing static route %I/%d\n", r->net, r->masklen); + DBG("Removing static route %I/%d via %I\n", r->net, r->masklen, r->via); n = net_find(p->table, r->net, r->masklen); rte_update(p, n, NULL); r->installed = 0; @@ -420,19 +420,24 @@ static_match(struct proto *p, struct static_route *r, struct static_config *n) if (r->neigh) r->neigh->data = NULL; + WALK_LIST(t, n->iface_routes) if (static_same_net(r, t)) - { - t->installed = r->installed && static_same_dest(r, t); - return; - } + goto found; + WALK_LIST(t, n->other_routes) if (static_same_net(r, t)) - { - t->installed = r->installed && static_same_dest(r, t); - return; - } + goto found; + static_remove(p, r); + return; + + found: + /* If destination is different, force reinstall */ + if ((r->installed > 0) && !static_same_dest(r, t)) + t->installed = -1; + else + t->installed = r->installed; } static inline rtable * diff --git a/proto/static/static.h b/proto/static/static.h index eb87ddec..99a0e68b 100644 --- a/proto/static/static.h +++ b/proto/static/static.h @@ -31,7 +31,7 @@ struct static_route { struct neighbor *neigh; byte *if_name; /* Name for RTD_DEVICE routes */ struct static_route *mp_next; /* Nexthops for RTD_MULTIPATH routes */ - int installed; /* Installed in master table */ + int installed; /* Installed in rt table, -1 for reinstall */ }; /* Dummy nodes (parts of multipath route) abuses masklen field for weight