BGP_TRACE(D_EVENTS, "Adding TCP-AO key %d/%d", key->key.send_id, key->key.recv_id);
/* Handle listening sockets */
- struct bgp_listen_request *blr; node *nxt;
+ struct bgp_listen_request *blr, *failed = NULL; node *nxt;
WALK_LIST2(blr, nxt, p->listen, pn)
- if (bgp_sk_add_ao_key(p, blr->sock->sk, key, "listening") < 0)
+ BGP_SOCKET_LOCKED(blr->sock, bs)
+ if (bgp_sk_add_ao_key(p, bs->sk, key, "listening") < 0)
{
- key->failed = 1;
- return -1;
+ failed = blr;
+ goto failA;
}
- key->active = 1;
-
/* Handle incoming socket */
if (p->incoming_conn.sk)
if (bgp_sk_add_ao_key(p, p->incoming_conn.sk, key, "session (in)") < 0)
/* Handle outgoing socket */
if (p->outgoing_conn.sk)
if (bgp_sk_add_ao_key(p, p->outgoing_conn.sk, key, "session (out)") < 0)
- return -1;
+ goto failB;
+ key->active = 1;
return 0;
-
- bgp_sk_delete_ao_key(p, blr->sock->sk, key, NULL, -1, -1, "listening");
+
+ failB:
+ /* Cleanup incoming socket */
+ if (p->incoming_conn.sk)
+ bgp_sk_delete_ao_key(p, p->incoming_conn.sk, key, NULL, -1, -1, "session (in)");
+
+ failA:
+ /* Cleanup listening sockets */
+ WALK_LIST2(blr, nxt, p->listen, pn)
+ {
+ if (blr == failed)
+ break;
++ BGP_SOCKET_LOCKED(blr->sock, bs)
++ bgp_sk_delete_ao_key(p, bs->sk, key, NULL, -1, -1, "listening");
+ }
+
+ /* Mark as failed */
+ key->failed = 1;
+ return -1;
}
struct bgp_active_keys {
/* Handle listening socket */
struct bgp_listen_request *blr; node *nxt;
WALK_LIST2(blr, nxt, p->listen, pn)
- if (bgp_sk_delete_ao_key(p, blr->sock->sk, key, NULL, -1, -1, "listening") < 0)
+ BGP_SOCKET_LOCKED(blr->sock, bs)
+ if (bgp_sk_delete_ao_key(p, bs->sk, key, NULL, -1, -1, "listening") < 0)
- return -1;
+ rv = -1;
key->active = 0;
ASSERT_DIE(p->cf->ipatt);
ASSERT_DIE(p->cf->strict_bind);
- if ((ps == PS_DOWN) || (ps == PS_STOP))
+ if ((ps == PS_DOWN_XX) || (ps == PS_FLUSH) || (ps == PS_STOP))
- return;
+ return false;
if (!iface_patt_match(p->cf->ipatt, i, NULL))
- return;
+ return false;
+
+ return true;
+ }
+ static void
+ bgp_iface_update(struct bgp_proto *p, uint flags, struct iface *i)
+ {
struct bgp_socket_params params = {
.iface = i,
.vrf = p->p.vrf,
bgp_iface_update(p, flags, i->iface);
}
- struct iface *iface;
+ static void
+ bgp_if_reload(struct bgp_proto *p, struct iface_patt *patt)
+ {
- WALK_LIST(iface, iface_list)
+ struct ifa *a;
+
++ IFACE_WALK(iface)
+ {
+ bool old = iface_patt_match(p->cf->ipatt, iface, NULL);
+ bool new = iface_patt_match(patt, iface, NULL);
+
+ if (old == new)
+ continue;
+
+ if (ipa_zero(p->cf->local_ip) || p->cf->free_bind)
+ bgp_iface_update(p, old ? IF_CHANGE_DOWN : IF_CHANGE_UP, iface);
+ else
+ WALK_LIST(a, iface->addrs)
+ if (ipa_equal(a->ip, p->cf->local_ip))
+ bgp_iface_update(p, old ? IF_CHANGE_DOWN : IF_CHANGE_UP, iface);
+ }
+ }
+
static void
bgp_neigh_notify(neighbor *n)
{
/* Initialize listening socket list */
init_list(&p->listen);
- P->if_notify = NULL;
- P->ifa_notify = NULL;
+ /* Setup interface notification hooks */
- P->if_notify = bgp_if_notify;
++ P->iface_sub.if_notify = NULL;
++ P->iface_sub.ifa_notify = NULL;
+ if (cf->ipatt) {
+ if (ipa_zero(cf->local_ip) || cf->free_bind)
- P->ifa_notify = bgp_ifa_notify;
++ P->iface_sub.if_notify = bgp_if_notify;
+ else
++ P->iface_sub.ifa_notify = bgp_ifa_notify;
+ }
+
/* Initialize TCP-AO keys */
init_list(&p->ao.keys);
if (cf->auth_type == BGP_AUTH_AO)
p->remote_ip = cf->remote_ip;
p->remote_as = cf->remote_as;
- P->iface_sub.if_notify = (cf->ipatt && ipa_zero(cf->local_ip)) ? bgp_if_notify : NULL;
- P->iface_sub.ifa_notify = (cf->ipatt && !ipa_zero(cf->local_ip)) ? bgp_ifa_notify : NULL;
-
+ p->postponed_sk = NULL;
+
/* Hack: We use cf->remote_ip just to pass remote_ip from bgp_spawn() */
if (cf->c.parent)
cf->remote_ip = IPA_NONE;
&& !bstrcmp(old->dynamic_name, new->dynamic_name)
&& (old->dynamic_name_digits == new->dynamic_name_digits);
- /* Reconfigure TCP-AP */
+ /* Reconfigure interface notification hooks */
- same = same && (!P->if_notify == !(new->ipatt && ipa_zero(new->local_ip)));
- same = same && (!P->ifa_notify == !(new->ipatt && !ipa_zero(new->local_ip)));
++ same = same && (!P->iface_sub.if_notify == !(new->ipatt && ipa_zero(new->local_ip)));
++ same = same && (!P->iface_sub.ifa_notify == !(new->ipatt && !ipa_zero(new->local_ip)));
+
+ /* Differing pattern lists cause an update of the listening sockets
+ * and also if the connection is up, then active sockets. */
+ bool need_if_reload = same && new->ipatt && old->ipatt && !iface_plists_equal(new->ipatt, old->ipatt);
+ if (need_if_reload && !bgp_is_dynamic(p) && (
+ p->incoming_conn.sk && !iface_patt_match(new->ipatt, p->incoming_conn.sk->iface, NULL) ||
+ p->outgoing_conn.sk && !iface_patt_match(new->ipatt, p->outgoing_conn.sk->iface, NULL)))
+ same = 0;
+
+ /* Reconfigure TCP-AO */
same = same && bgp_reconfigure_ao_keys(p, new);
/* FIXME: Move channel reconfiguration to generic protocol code ? */
if (((co->state == BS_OPENCONFIRM) || (co->state == BS_ESTABLISHED)) && !bgp_check_capabilities(co))
return 0;
- proto_setup_mpls_map(P, RTS_BGP, 1);
-
- if (p->start_state > BSS_PREPARE)
+ if (bgp_start_state(p) > BSS_PREPARE)
bgp_update_bfd(p, new->bfd);
+ if (need_if_reload)
+ bgp_if_reload(p, new->ipatt);
+
return 1;
}