summaryrefslogtreecommitdiff
path: root/nest/iface.c
diff options
context:
space:
mode:
Diffstat (limited to 'nest/iface.c')
-rw-r--r--nest/iface.c119
1 files changed, 94 insertions, 25 deletions
diff --git a/nest/iface.c b/nest/iface.c
index 682340c5..78f4eb0f 100644
--- a/nest/iface.c
+++ b/nest/iface.c
@@ -36,9 +36,12 @@
static pool *if_pool;
-list iface_list;
+DOMAIN(attrs) iface_domain;
+list global_iface_list;
+struct iface default_vrf;
static void if_recalc_preferred(struct iface *i);
+static void ifa_delete_locked(struct ifa *a);
/**
* ifa_dump - dump interface address
@@ -49,6 +52,7 @@ static void if_recalc_preferred(struct iface *i);
void
ifa_dump(struct ifa *a)
{
+ IFACE_LEGACY_ACCESS;
debug("\t%I, net %N bc %I -> %I%s%s%s%s\n", a->ip, &a->prefix, a->brd, a->opposite,
(a->flags & IA_PRIMARY) ? " PRIMARY" : "",
(a->flags & IA_SECONDARY) ? " SEC" : "",
@@ -68,6 +72,7 @@ if_dump(struct iface *i)
{
struct ifa *a;
+ IFACE_LEGACY_ACCESS;
debug("IF%d: %s", i->index, i->name);
if (i->flags & IF_SHUTDOWN)
debug(" SHUTDOWN");
@@ -109,8 +114,9 @@ if_dump_all(void)
{
struct iface *i;
+ IFACE_LEGACY_ACCESS;
debug("Known network interfaces:\n");
- WALK_LIST(i, iface_list)
+ WALK_LIST(i, global_iface_list)
if_dump(i);
debug("Router ID: %08x\n", config->router_id);
}
@@ -147,7 +153,7 @@ ifa_send_notify(struct proto *p, unsigned c, struct ifa *a)
{
if (p->ifa_notify &&
(p->proto_state != PS_DOWN) &&
- (!p->vrf_set || p->vrf == a->iface->master))
+ (!p->vrf || p->vrf == a->iface->master))
{
if (p->debug & D_IFACES)
log(L_TRACE "%s < address %N on interface %s %s",
@@ -165,7 +171,8 @@ ifa_notify_change_(unsigned c, struct ifa *a)
DBG("IFA change notification (%x) for %s:%I\n", c, a->iface->name, a->ip);
WALK_LIST(p, proto_list)
- ifa_send_notify(p, c, a);
+ PROTO_LOCKED_FROM_MAIN(p)
+ ifa_send_notify(p, c, a);
}
static inline void
@@ -185,7 +192,7 @@ if_send_notify(struct proto *p, unsigned c, struct iface *i)
{
if (p->if_notify &&
(p->proto_state != PS_DOWN) &&
- (!p->vrf_set || p->vrf == i->master))
+ (!p->vrf || p->vrf == i->master))
{
if (p->debug & D_IFACES)
log(L_TRACE "%s < interface %s %s", p->name, i->name,
@@ -225,7 +232,8 @@ if_notify_change(unsigned c, struct iface *i)
ifa_notify_change_(IF_CHANGE_DOWN, a);
WALK_LIST(p, proto_list)
- if_send_notify(p, c, i);
+ PROTO_LOCKED_FROM_MAIN(p)
+ if_send_notify(p, c, i);
if (c & IF_CHANGE_UP)
WALK_LIST(a, i->addrs)
@@ -243,7 +251,7 @@ if_recalc_flags(struct iface *i UNUSED, uint flags)
{
if ((flags & IF_ADMIN_UP) &&
!(flags & (IF_SHUTDOWN | IF_TMP_DOWN)) &&
- !(i->master_index && !i->master))
+ !(i->master_index && i->master == &default_vrf))
flags |= IF_UP;
else
flags &= ~IF_UP;
@@ -301,7 +309,13 @@ if_update(struct iface *new)
struct iface *i;
unsigned c;
- WALK_LIST(i, iface_list)
+ if (!new->master)
+ new->master = &default_vrf;
+
+ IFACE_LEGACY_ACCESS;
+ IFACE_LOCK;
+
+ WALK_LIST(i, global_iface_list)
if (!strcmp(new->name, i->name))
{
new->flags = if_recalc_flags(new, new->flags);
@@ -322,6 +336,8 @@ if_update(struct iface *new)
}
if_copy(i, new);
+ IFACE_UNLOCK;
+
if (c)
if_notify_change(c, i);
@@ -334,7 +350,9 @@ if_update(struct iface *new)
newif:
init_list(&i->neighbors);
i->flags |= IF_UPDATED | IF_TMP_DOWN; /* Tmp down as we don't have addresses yet */
- add_tail(&iface_list, &i->n);
+ add_tail(&global_iface_list, &i->n);
+ IFACE_UNLOCK;
+
return i;
}
@@ -344,7 +362,8 @@ if_start_update(void)
struct iface *i;
struct ifa *a;
- WALK_LIST(i, iface_list)
+ IFACE_LEGACY_ACCESS;
+ WALK_LIST(i, global_iface_list)
{
i->flags &= ~IF_UPDATED;
WALK_LIST(a, i->addrs)
@@ -355,6 +374,8 @@ if_start_update(void)
void
if_end_partial_update(struct iface *i)
{
+ IFACE_LEGACY_ACCESS;
+
if (i->flags & IF_NEEDS_RECALC)
if_recalc_preferred(i);
@@ -368,7 +389,8 @@ if_end_update(void)
struct iface *i;
struct ifa *a, *b;
- WALK_LIST(i, iface_list)
+ IFACE_LEGACY_ACCESS;
+ WALK_LIST(i, global_iface_list)
{
if (!(i->flags & IF_UPDATED))
if_change_flags(i, (i->flags & ~IF_ADMIN_UP) | IF_SHUTDOWN);
@@ -376,7 +398,11 @@ if_end_update(void)
{
WALK_LIST_DELSAFE(a, b, i->addrs)
if (!(a->flags & IA_UPDATED))
- ifa_delete(a);
+ {
+ IFACE_LOCK;
+ ifa_delete_locked(a);
+ IFACE_UNLOCK;
+ }
if_end_partial_update(i);
}
}
@@ -385,6 +411,7 @@ if_end_update(void)
void
if_flush_ifaces(struct proto *p)
{
+ IFACE_LEGACY_ACCESS;
if (p->debug & D_EVENTS)
log(L_TRACE "%s: Flushing interfaces", p->name);
if_start_update();
@@ -404,10 +431,12 @@ if_feed_baby(struct proto *p)
struct iface *i;
struct ifa *a;
+ IFACE_LEGACY_ACCESS;
+
if (!p->if_notify && !p->ifa_notify) /* shortcut */
return;
DBG("Announcing interfaces to new protocol %s\n", p->name);
- WALK_LIST(i, iface_list)
+ WALK_LIST(i, global_iface_list)
{
if_send_notify(p, IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0), i);
if (i->flags & IF_UP)
@@ -429,9 +458,15 @@ if_find_by_index(unsigned idx)
{
struct iface *i;
- WALK_LIST(i, iface_list)
+ IFACE_LOCK;
+ WALK_LIST(i, global_iface_list)
if (i->index == idx && !(i->flags & IF_SHUTDOWN))
+ {
+ IFACE_UNLOCK;
return i;
+ }
+
+ IFACE_UNLOCK;
return NULL;
}
@@ -448,9 +483,15 @@ if_find_by_name(const char *name)
{
struct iface *i;
- WALK_LIST(i, iface_list)
+ IFACE_LOCK;
+ WALK_LIST(i, global_iface_list)
if (!strcmp(i->name, name) && !(i->flags & IF_SHUTDOWN))
+ {
+ IFACE_UNLOCK;
return i;
+ }
+
+ IFACE_UNLOCK;
return NULL;
}
@@ -459,17 +500,21 @@ if_get_by_name(const char *name)
{
struct iface *i;
- WALK_LIST(i, iface_list)
+ IFACE_LEGACY_ACCESS;
+
+ WALK_LIST(i, global_iface_list)
if (!strcmp(i->name, name))
return i;
/* No active iface, create a dummy */
+ IFACE_LOCK;
i = mb_allocz(if_pool, sizeof(struct iface));
strncpy(i->name, name, sizeof(i->name)-1);
i->flags = IF_SHUTDOWN;
init_list(&i->addrs);
init_list(&i->neighbors);
- add_tail(&iface_list, &i->n);
+ add_tail(&global_iface_list, &i->n);
+ IFACE_UNLOCK;
return i;
}
@@ -555,7 +600,9 @@ if_recalc_all_preferred_addresses(void)
{
struct iface *i;
- WALK_LIST(i, iface_list)
+ IFACE_LEGACY_ACCESS;
+
+ WALK_LIST(i, global_iface_list)
{
if_recalc_preferred(i);
@@ -585,6 +632,8 @@ ifa_update(struct ifa *a)
struct iface *i = a->iface;
struct ifa *b;
+ IFACE_LEGACY_ACCESS;
+
WALK_LIST(b, i->addrs)
if (ifa_same(b, a))
{
@@ -603,10 +652,12 @@ ifa_update(struct ifa *a)
if ((a->prefix.type == NET_IP4) && (i->flags & IF_BROADCAST) && ipa_zero(a->brd))
log(L_WARN "Missing broadcast address for interface %s", i->name);
+ IFACE_LOCK;
b = mb_alloc(if_pool, sizeof(struct ifa));
memcpy(b, a, sizeof(struct ifa));
add_tail(&i->addrs, &b->n);
b->flags |= IA_UPDATED;
+ IFACE_UNLOCK;
i->flags |= IF_NEEDS_RECALC;
if (i->flags & IF_UP)
@@ -631,6 +682,17 @@ ifa_delete(struct ifa *a)
WALK_LIST(b, i->addrs)
if (ifa_same(b, a))
{
+ IFACE_LOCK;
+ ifa_delete_locked(b);
+ IFACE_UNLOCK;
+ return;
+ }
+}
+
+static void
+ifa_delete_locked(struct ifa *b)
+{
+ struct iface *i = b->iface;
rem_node(&b->n);
if (b->flags & IA_PRIMARY)
@@ -653,7 +715,6 @@ ifa_delete(struct ifa *a)
mb_free(b);
return;
- }
}
u32
@@ -662,8 +723,10 @@ if_choose_router_id(struct iface_patt *mask, u32 old_id)
struct iface *i;
struct ifa *a, *b;
+ IFACE_LEGACY_ACCESS;
+
b = NULL;
- WALK_LIST(i, iface_list)
+ WALK_LIST(i, global_iface_list)
{
if (!(i->flags & IF_ADMIN_UP) ||
(i->flags & IF_SHUTDOWN))
@@ -709,8 +772,10 @@ if_choose_router_id(struct iface_patt *mask, u32 old_id)
void
if_init(void)
{
- if_pool = rp_new(&root_pool, "Interfaces");
- init_list(&iface_list);
+ iface_domain = DOMAIN_NEW(attrs, "Interfaces");
+ if_pool = rp_new(&root_pool, &main_birdloop, "Interfaces");
+ init_list(&global_iface_list);
+ strcpy(default_vrf.name, "default");
neigh_init(if_pool);
}
@@ -837,13 +902,15 @@ if_show(void)
struct ifa *a;
char *type;
- WALK_LIST(i, iface_list)
+ IFACE_LEGACY_ACCESS;
+
+ WALK_LIST(i, global_iface_list)
{
if (i->flags & IF_SHUTDOWN)
continue;
char mbuf[16 + sizeof(i->name)] = {};
- if (i->master)
+ if (i->master != &default_vrf)
bsprintf(mbuf, " master=%s", i->master->name);
else if (i->master_index)
bsprintf(mbuf, " master=#%u", i->master_index);
@@ -879,8 +946,10 @@ if_show_summary(void)
{
struct iface *i;
+ IFACE_LEGACY_ACCESS;
+
cli_msg(-2005, "%-10s %-6s %-18s %s", "Interface", "State", "IPv4 address", "IPv6 address");
- WALK_LIST(i, iface_list)
+ WALK_LIST(i, global_iface_list)
{
byte a4[IPA_MAX_TEXT_LENGTH + 17];
byte a6[IPA_MAX_TEXT_LENGTH + 17];