summaryrefslogtreecommitdiff
path: root/nest/neighbor.c
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2012-01-01 12:02:20 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2012-01-01 12:14:42 +0100
commit69a8259c5e438f949bd58b1a2f8e1d12a49f9216 (patch)
tree5d685368ce58732ce4a9133b5f5bc43b20b78476 /nest/neighbor.c
parentc32c3f88f0c8788118ed3701c11a5aea2aaf9356 (diff)
Allows sticky link-local neighbors.
Allows using NEF_STICKY neighbors with link-local addresses. This is used for static route nexthops, they can be specified like fe80::1%eth0 .
Diffstat (limited to 'nest/neighbor.c')
-rw-r--r--nest/neighbor.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/nest/neighbor.c b/nest/neighbor.c
index 67bd32b3..506d9bde 100644
--- a/nest/neighbor.c
+++ b/nest/neighbor.c
@@ -133,6 +133,7 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
if (ifa)
{
scope = if_connected(a, ifa);
+ flags |= NEF_BIND;
if ((scope < 0) && (flags & NEF_ONLINK))
scope = class & IADDR_SCOPE_MASK;
@@ -160,10 +161,7 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
}
else
{
- /* sticky flag does not work for link-local neighbors;
- fortunately, we don't use this combination */
add_tail(&sticky_neigh_list, &n->n);
- ifa = NULL;
scope = -1;
}
n->iface = ifa;
@@ -235,7 +233,9 @@ neigh_down(neighbor *n)
{
DBG("Flushing neighbor %I on %s\n", n->addr, i->name);
rem_node(&n->if_n);
- n->iface = NULL;
+ if (! (n->flags & NEF_BIND))
+ n->iface = NULL;
+ n->scope = -1;
if (n->proto->neigh_notify && n->proto->core_state != FS_FLUSHING)
n->proto->neigh_notify(n);
rem_node(&n->n);
@@ -262,7 +262,8 @@ neigh_if_up(struct iface *i)
int scope;
WALK_LIST_DELSAFE(n, next, sticky_neigh_list)
- if ((scope = if_connected(&n->addr, i)) >= 0)
+ if ((!n->iface || n->iface == i) &&
+ ((scope = if_connected(&n->addr, i)) >= 0))
neigh_up(n, i, scope);
}
@@ -339,7 +340,7 @@ neigh_prune_one(neighbor *n)
if (n->proto->proto_state != PS_DOWN)
return;
rem_node(&n->n);
- if (n->iface)
+ if (n->scope >= 0)
rem_node(&n->if_n);
sl_free(neigh_slab, n);
}