diff options
Diffstat (limited to 'bgpd/bgpd.c')
| -rw-r--r-- | bgpd/bgpd.c | 13345 |
1 files changed, 6505 insertions, 6840 deletions
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 1b0d78ff9a..3453da665a 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -93,18 +93,17 @@ struct community_list_handler *bgp_clist; unsigned int multipath_num = MULTIPATH_NUM; -static void bgp_if_finish (struct bgp *bgp); +static void bgp_if_finish(struct bgp *bgp); extern struct zclient *zclient; -void -bgp_session_reset(struct peer *peer) +void bgp_session_reset(struct peer *peer) { - if (peer->doppelganger && (peer->doppelganger->status != Deleted) - && !(CHECK_FLAG(peer->doppelganger->flags, PEER_FLAG_CONFIG_NODE))) - peer_delete(peer->doppelganger); + if (peer->doppelganger && (peer->doppelganger->status != Deleted) + && !(CHECK_FLAG(peer->doppelganger->flags, PEER_FLAG_CONFIG_NODE))) + peer_delete(peer->doppelganger); - BGP_EVENT_ADD (peer, BGP_Stop); + BGP_EVENT_ADD(peer, BGP_Stop); } /* @@ -113,1145 +112,1061 @@ bgp_session_reset(struct peer *peer) * during walk of peer list, we would end up accessing the freed next * node. This function moves the next node along. */ -static void -bgp_session_reset_safe(struct peer *peer, struct listnode **nnode) +static void bgp_session_reset_safe(struct peer *peer, struct listnode **nnode) { - struct listnode *n; - struct peer *npeer; + struct listnode *n; + struct peer *npeer; - n = (nnode) ? *nnode : NULL; - npeer = (n) ? listgetdata(n) : NULL; + n = (nnode) ? *nnode : NULL; + npeer = (n) ? listgetdata(n) : NULL; - if (peer->doppelganger && (peer->doppelganger->status != Deleted) - && !(CHECK_FLAG(peer->doppelganger->flags, PEER_FLAG_CONFIG_NODE))) - { - if (peer->doppelganger == npeer) - /* nnode and *nnode are confirmed to be non-NULL here */ - *nnode = (*nnode)->next; - peer_delete(peer->doppelganger); - } + if (peer->doppelganger && (peer->doppelganger->status != Deleted) + && !(CHECK_FLAG(peer->doppelganger->flags, + PEER_FLAG_CONFIG_NODE))) { + if (peer->doppelganger == npeer) + /* nnode and *nnode are confirmed to be non-NULL here */ + *nnode = (*nnode)->next; + peer_delete(peer->doppelganger); + } - BGP_EVENT_ADD (peer, BGP_Stop); + BGP_EVENT_ADD(peer, BGP_Stop); } /* BGP global flag manipulation. */ -int -bgp_option_set (int flag) -{ - switch (flag) - { - case BGP_OPT_NO_FIB: - case BGP_OPT_MULTIPLE_INSTANCE: - case BGP_OPT_CONFIG_CISCO: - case BGP_OPT_NO_LISTEN: - SET_FLAG (bm->options, flag); - break; - default: - return BGP_ERR_INVALID_FLAG; - } - return 0; -} - -int -bgp_option_unset (int flag) -{ - switch (flag) - { - case BGP_OPT_MULTIPLE_INSTANCE: - if (listcount (bm->bgp) > 1) - return BGP_ERR_MULTIPLE_INSTANCE_USED; - /* Fall through. */ - case BGP_OPT_NO_FIB: - case BGP_OPT_CONFIG_CISCO: - UNSET_FLAG (bm->options, flag); - break; - default: - return BGP_ERR_INVALID_FLAG; - } - return 0; -} - -int -bgp_option_check (int flag) -{ - return CHECK_FLAG (bm->options, flag); +int bgp_option_set(int flag) +{ + switch (flag) { + case BGP_OPT_NO_FIB: + case BGP_OPT_MULTIPLE_INSTANCE: + case BGP_OPT_CONFIG_CISCO: + case BGP_OPT_NO_LISTEN: + SET_FLAG(bm->options, flag); + break; + default: + return BGP_ERR_INVALID_FLAG; + } + return 0; +} + +int bgp_option_unset(int flag) +{ + switch (flag) { + case BGP_OPT_MULTIPLE_INSTANCE: + if (listcount(bm->bgp) > 1) + return BGP_ERR_MULTIPLE_INSTANCE_USED; + /* Fall through. */ + case BGP_OPT_NO_FIB: + case BGP_OPT_CONFIG_CISCO: + UNSET_FLAG(bm->options, flag); + break; + default: + return BGP_ERR_INVALID_FLAG; + } + return 0; +} + +int bgp_option_check(int flag) +{ + return CHECK_FLAG(bm->options, flag); } /* BGP flag manipulation. */ -int -bgp_flag_set (struct bgp *bgp, int flag) +int bgp_flag_set(struct bgp *bgp, int flag) { - SET_FLAG (bgp->flags, flag); - return 0; + SET_FLAG(bgp->flags, flag); + return 0; } -int -bgp_flag_unset (struct bgp *bgp, int flag) +int bgp_flag_unset(struct bgp *bgp, int flag) { - UNSET_FLAG (bgp->flags, flag); - return 0; + UNSET_FLAG(bgp->flags, flag); + return 0; } -int -bgp_flag_check (struct bgp *bgp, int flag) +int bgp_flag_check(struct bgp *bgp, int flag) { - return CHECK_FLAG (bgp->flags, flag); + return CHECK_FLAG(bgp->flags, flag); } /* Internal function to set BGP structure configureation flag. */ -static void -bgp_config_set (struct bgp *bgp, int config) +static void bgp_config_set(struct bgp *bgp, int config) { - SET_FLAG (bgp->config, config); + SET_FLAG(bgp->config, config); } -static void -bgp_config_unset (struct bgp *bgp, int config) +static void bgp_config_unset(struct bgp *bgp, int config) { - UNSET_FLAG (bgp->config, config); + UNSET_FLAG(bgp->config, config); } -static int -bgp_config_check (struct bgp *bgp, int config) +static int bgp_config_check(struct bgp *bgp, int config) { - return CHECK_FLAG (bgp->config, config); + return CHECK_FLAG(bgp->config, config); } /* Set BGP router identifier. */ -static int -bgp_router_id_set (struct bgp *bgp, const struct in_addr *id) +static int bgp_router_id_set(struct bgp *bgp, const struct in_addr *id) { - struct peer *peer; - struct listnode *node, *nnode; + struct peer *peer; + struct listnode *node, *nnode; - if (IPV4_ADDR_SAME (&bgp->router_id, id)) - return 0; + if (IPV4_ADDR_SAME(&bgp->router_id, id)) + return 0; - /* EVPN uses router id in RD, withdraw them */ - if (bgp->advertise_all_vni) - bgp_evpn_handle_router_id_update (bgp, TRUE); + /* EVPN uses router id in RD, withdraw them */ + if (bgp->advertise_all_vni) + bgp_evpn_handle_router_id_update(bgp, TRUE); - IPV4_ADDR_COPY (&bgp->router_id, id); + IPV4_ADDR_COPY(&bgp->router_id, id); - /* Set all peer's local identifier with this value. */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - IPV4_ADDR_COPY (&peer->local_id, id); + /* Set all peer's local identifier with this value. */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + IPV4_ADDR_COPY(&peer->local_id, id); - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_RID_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - } + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_RID_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } + } - /* EVPN uses router id in RD, update them */ - if (bgp->advertise_all_vni) - bgp_evpn_handle_router_id_update (bgp, FALSE); + /* EVPN uses router id in RD, update them */ + if (bgp->advertise_all_vni) + bgp_evpn_handle_router_id_update(bgp, FALSE); - return 0; + return 0; } -void -bgp_router_id_zebra_bump (vrf_id_t vrf_id, const struct prefix *router_id) +void bgp_router_id_zebra_bump(vrf_id_t vrf_id, const struct prefix *router_id) { - struct listnode *node, *nnode; - struct bgp *bgp; + struct listnode *node, *nnode; + struct bgp *bgp; - if (vrf_id == VRF_DEFAULT) - { - /* Router-id change for default VRF has to also update all views. */ - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - { - if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) - continue; + if (vrf_id == VRF_DEFAULT) { + /* Router-id change for default VRF has to also update all + * views. */ + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { + if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) + continue; - bgp->router_id_zebra = router_id->u.prefix4; - if (!bgp->router_id_static.s_addr) - bgp_router_id_set (bgp, &router_id->u.prefix4); - } - } - else - { - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (bgp) - { - bgp->router_id_zebra = router_id->u.prefix4; + bgp->router_id_zebra = router_id->u.prefix4; + if (!bgp->router_id_static.s_addr) + bgp_router_id_set(bgp, &router_id->u.prefix4); + } + } else { + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (bgp) { + bgp->router_id_zebra = router_id->u.prefix4; - if (!bgp->router_id_static.s_addr) - bgp_router_id_set (bgp, &router_id->u.prefix4); - } - } + if (!bgp->router_id_static.s_addr) + bgp_router_id_set(bgp, &router_id->u.prefix4); + } + } } -int -bgp_router_id_static_set (struct bgp *bgp, struct in_addr id) +int bgp_router_id_static_set(struct bgp *bgp, struct in_addr id) { - bgp->router_id_static = id; - bgp_router_id_set (bgp, id.s_addr ? &id : &bgp->router_id_zebra); - return 0; + bgp->router_id_static = id; + bgp_router_id_set(bgp, id.s_addr ? &id : &bgp->router_id_zebra); + return 0; } /* BGP's cluster-id control. */ -int -bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id) +int bgp_cluster_id_set(struct bgp *bgp, struct in_addr *cluster_id) { - struct peer *peer; - struct listnode *node, *nnode; + struct peer *peer; + struct listnode *node, *nnode; - if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID) - && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id)) - return 0; + if (bgp_config_check(bgp, BGP_CONFIG_CLUSTER_ID) + && IPV4_ADDR_SAME(&bgp->cluster_id, cluster_id)) + return 0; - IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id); - bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID); + IPV4_ADDR_COPY(&bgp->cluster_id, cluster_id); + bgp_config_set(bgp, BGP_CONFIG_CLUSTER_ID); - /* Clear all IBGP peer. */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->sort != BGP_PEER_IBGP) - continue; + /* Clear all IBGP peer. */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->sort != BGP_PEER_IBGP) + continue; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_CLID_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - } - return 0; + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_CLID_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } + } + return 0; } -int -bgp_cluster_id_unset (struct bgp *bgp) +int bgp_cluster_id_unset(struct bgp *bgp) { - struct peer *peer; - struct listnode *node, *nnode; + struct peer *peer; + struct listnode *node, *nnode; - if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)) - return 0; + if (!bgp_config_check(bgp, BGP_CONFIG_CLUSTER_ID)) + return 0; - bgp->cluster_id.s_addr = 0; - bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID); + bgp->cluster_id.s_addr = 0; + bgp_config_unset(bgp, BGP_CONFIG_CLUSTER_ID); - /* Clear all IBGP peer. */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->sort != BGP_PEER_IBGP) - continue; + /* Clear all IBGP peer. */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->sort != BGP_PEER_IBGP) + continue; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_CLID_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - } - return 0; + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_CLID_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } + } + return 0; } /* time_t value that is monotonicly increasing * and uneffected by adjustments to system clock */ -time_t bgp_clock (void) +time_t bgp_clock(void) { - struct timeval tv; + struct timeval tv; - monotime(&tv); - return tv.tv_sec; + monotime(&tv); + return tv.tv_sec; } /* BGP timer configuration. */ -int -bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime) +int bgp_timers_set(struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime) { - bgp->default_keepalive = (keepalive < holdtime / 3 - ? keepalive : holdtime / 3); - bgp->default_holdtime = holdtime; + bgp->default_keepalive = + (keepalive < holdtime / 3 ? keepalive : holdtime / 3); + bgp->default_holdtime = holdtime; - return 0; + return 0; } -int -bgp_timers_unset (struct bgp *bgp) +int bgp_timers_unset(struct bgp *bgp) { - bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE; - bgp->default_holdtime = BGP_DEFAULT_HOLDTIME; + bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE; + bgp->default_holdtime = BGP_DEFAULT_HOLDTIME; - return 0; + return 0; } /* BGP confederation configuration. */ -int -bgp_confederation_id_set (struct bgp *bgp, as_t as) -{ - struct peer *peer; - struct listnode *node, *nnode; - int already_confed; - - if (as == 0) - return BGP_ERR_INVALID_AS; - - /* Remember - were we doing confederation before? */ - already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION); - bgp->confed_id = as; - bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION); - - /* If we were doing confederation already, this is just an external - AS change. Just Reset EBGP sessions, not CONFED sessions. If we - were not doing confederation before, reset all EBGP sessions. */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - /* We're looking for peers who's AS is not local or part of our - confederation. */ - if (already_confed) - { - if (peer_sort (peer) == BGP_PEER_EBGP) - { - peer->local_as = as; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset_safe(peer, &nnode); - } - } - else - { - /* Not doign confederation before, so reset every non-local - session */ - if (peer_sort (peer) != BGP_PEER_IBGP) - { - /* Reset the local_as to be our EBGP one */ - if (peer_sort (peer) == BGP_PEER_EBGP) - peer->local_as = as; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset_safe(peer, &nnode); - } - } - } - return 0; -} - -int -bgp_confederation_id_unset (struct bgp *bgp) -{ - struct peer *peer; - struct listnode *node, *nnode; - - bgp->confed_id = 0; - bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION); - - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - /* We're looking for peers who's AS is not local */ - if (peer_sort (peer) != BGP_PEER_IBGP) - { - peer->local_as = bgp->as; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - - else - bgp_session_reset_safe(peer, &nnode); +int bgp_confederation_id_set(struct bgp *bgp, as_t as) +{ + struct peer *peer; + struct listnode *node, *nnode; + int already_confed; + + if (as == 0) + return BGP_ERR_INVALID_AS; + + /* Remember - were we doing confederation before? */ + already_confed = bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION); + bgp->confed_id = as; + bgp_config_set(bgp, BGP_CONFIG_CONFEDERATION); + + /* If we were doing confederation already, this is just an external + AS change. Just Reset EBGP sessions, not CONFED sessions. If we + were not doing confederation before, reset all EBGP sessions. */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + /* We're looking for peers who's AS is not local or part of our + confederation. */ + if (already_confed) { + if (peer_sort(peer) == BGP_PEER_EBGP) { + peer->local_as = as; + if (BGP_IS_VALID_STATE_FOR_NOTIF( + peer->status)) { + peer->last_reset = + PEER_DOWN_CONFED_ID_CHANGE; + bgp_notify_send( + peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset_safe(peer, &nnode); + } + } else { + /* Not doign confederation before, so reset every + non-local + session */ + if (peer_sort(peer) != BGP_PEER_IBGP) { + /* Reset the local_as to be our EBGP one */ + if (peer_sort(peer) == BGP_PEER_EBGP) + peer->local_as = as; + if (BGP_IS_VALID_STATE_FOR_NOTIF( + peer->status)) { + peer->last_reset = + PEER_DOWN_CONFED_ID_CHANGE; + bgp_notify_send( + peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset_safe(peer, &nnode); + } + } } - } - return 0; + return 0; } -/* Is an AS part of the confed or not? */ -int -bgp_confederation_peers_check (struct bgp *bgp, as_t as) +int bgp_confederation_id_unset(struct bgp *bgp) { - int i; + struct peer *peer; + struct listnode *node, *nnode; - if (! bgp) - return 0; + bgp->confed_id = 0; + bgp_config_unset(bgp, BGP_CONFIG_CONFEDERATION); - for (i = 0; i < bgp->confed_peers_cnt; i++) - if (bgp->confed_peers[i] == as) - return 1; - - return 0; + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + /* We're looking for peers who's AS is not local */ + if (peer_sort(peer) != BGP_PEER_IBGP) { + peer->local_as = bgp->as; + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } + + else + bgp_session_reset_safe(peer, &nnode); + } + } + return 0; } -/* Add an AS to the confederation set. */ -int -bgp_confederation_peers_add (struct bgp *bgp, as_t as) +/* Is an AS part of the confed or not? */ +int bgp_confederation_peers_check(struct bgp *bgp, as_t as) { - struct peer *peer; - struct listnode *node, *nnode; - - if (! bgp) - return BGP_ERR_INVALID_BGP; + int i; - if (bgp->as == as) - return BGP_ERR_INVALID_AS; + if (!bgp) + return 0; - if (bgp_confederation_peers_check (bgp, as)) - return -1; + for (i = 0; i < bgp->confed_peers_cnt; i++) + if (bgp->confed_peers[i] == as) + return 1; - if (bgp->confed_peers) - bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST, - bgp->confed_peers, - (bgp->confed_peers_cnt + 1) * sizeof (as_t)); - else - bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST, - (bgp->confed_peers_cnt + 1) * sizeof (as_t)); - - bgp->confed_peers[bgp->confed_peers_cnt] = as; - bgp->confed_peers_cnt++; + return 0; +} - if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)) - { - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->as == as) - { - peer->local_as = bgp->as; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset_safe(peer, &nnode); - } - } - } - return 0; +/* Add an AS to the confederation set. */ +int bgp_confederation_peers_add(struct bgp *bgp, as_t as) +{ + struct peer *peer; + struct listnode *node, *nnode; + + if (!bgp) + return BGP_ERR_INVALID_BGP; + + if (bgp->as == as) + return BGP_ERR_INVALID_AS; + + if (bgp_confederation_peers_check(bgp, as)) + return -1; + + if (bgp->confed_peers) + bgp->confed_peers = + XREALLOC(MTYPE_BGP_CONFED_LIST, bgp->confed_peers, + (bgp->confed_peers_cnt + 1) * sizeof(as_t)); + else + bgp->confed_peers = + XMALLOC(MTYPE_BGP_CONFED_LIST, + (bgp->confed_peers_cnt + 1) * sizeof(as_t)); + + bgp->confed_peers[bgp->confed_peers_cnt] = as; + bgp->confed_peers_cnt++; + + if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) { + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->as == as) { + peer->local_as = bgp->as; + if (BGP_IS_VALID_STATE_FOR_NOTIF( + peer->status)) { + peer->last_reset = + PEER_DOWN_CONFED_PEER_CHANGE; + bgp_notify_send( + peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset_safe(peer, &nnode); + } + } + } + return 0; } /* Delete an AS from the confederation set. */ -int -bgp_confederation_peers_remove (struct bgp *bgp, as_t as) -{ - int i; - int j; - struct peer *peer; - struct listnode *node, *nnode; - - if (! bgp) - return -1; - - if (! bgp_confederation_peers_check (bgp, as)) - return -1; - - for (i = 0; i < bgp->confed_peers_cnt; i++) - if (bgp->confed_peers[i] == as) - for(j = i + 1; j < bgp->confed_peers_cnt; j++) - bgp->confed_peers[j - 1] = bgp->confed_peers[j]; - - bgp->confed_peers_cnt--; - - if (bgp->confed_peers_cnt == 0) - { - if (bgp->confed_peers) - XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers); - bgp->confed_peers = NULL; - } - else - bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST, - bgp->confed_peers, - bgp->confed_peers_cnt * sizeof (as_t)); - - /* Now reset any peer who's remote AS has just been removed from the - CONFED */ - if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)) - { - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->as == as) - { - peer->local_as = bgp->confed_id; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset_safe(peer, &nnode); - } +int bgp_confederation_peers_remove(struct bgp *bgp, as_t as) +{ + int i; + int j; + struct peer *peer; + struct listnode *node, *nnode; + + if (!bgp) + return -1; + + if (!bgp_confederation_peers_check(bgp, as)) + return -1; + + for (i = 0; i < bgp->confed_peers_cnt; i++) + if (bgp->confed_peers[i] == as) + for (j = i + 1; j < bgp->confed_peers_cnt; j++) + bgp->confed_peers[j - 1] = bgp->confed_peers[j]; + + bgp->confed_peers_cnt--; + + if (bgp->confed_peers_cnt == 0) { + if (bgp->confed_peers) + XFREE(MTYPE_BGP_CONFED_LIST, bgp->confed_peers); + bgp->confed_peers = NULL; + } else + bgp->confed_peers = + XREALLOC(MTYPE_BGP_CONFED_LIST, bgp->confed_peers, + bgp->confed_peers_cnt * sizeof(as_t)); + + /* Now reset any peer who's remote AS has just been removed from the + CONFED */ + if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) { + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->as == as) { + peer->local_as = bgp->confed_id; + if (BGP_IS_VALID_STATE_FOR_NOTIF( + peer->status)) { + peer->last_reset = + PEER_DOWN_CONFED_PEER_CHANGE; + bgp_notify_send( + peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset_safe(peer, &nnode); + } + } } - } - return 0; + return 0; } /* Local preference configuration. */ -int -bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref) +int bgp_default_local_preference_set(struct bgp *bgp, u_int32_t local_pref) { - if (! bgp) - return -1; + if (!bgp) + return -1; - bgp->default_local_pref = local_pref; + bgp->default_local_pref = local_pref; - return 0; + return 0; } -int -bgp_default_local_preference_unset (struct bgp *bgp) +int bgp_default_local_preference_unset(struct bgp *bgp) { - if (! bgp) - return -1; + if (!bgp) + return -1; - bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF; + bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF; - return 0; + return 0; } /* Local preference configuration. */ -int -bgp_default_subgroup_pkt_queue_max_set (struct bgp *bgp, u_int32_t queue_size) +int bgp_default_subgroup_pkt_queue_max_set(struct bgp *bgp, + u_int32_t queue_size) { - if (! bgp) - return -1; + if (!bgp) + return -1; - bgp->default_subgroup_pkt_queue_max = queue_size; + bgp->default_subgroup_pkt_queue_max = queue_size; - return 0; + return 0; } -int -bgp_default_subgroup_pkt_queue_max_unset (struct bgp *bgp) +int bgp_default_subgroup_pkt_queue_max_unset(struct bgp *bgp) { - if (! bgp) - return -1; - bgp->default_subgroup_pkt_queue_max = BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX; + if (!bgp) + return -1; + bgp->default_subgroup_pkt_queue_max = + BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX; - return 0; + return 0; } /* Listen limit configuration. */ -int -bgp_listen_limit_set (struct bgp *bgp, int listen_limit) +int bgp_listen_limit_set(struct bgp *bgp, int listen_limit) { - if (! bgp) - return -1; + if (!bgp) + return -1; - bgp->dynamic_neighbors_limit = listen_limit; + bgp->dynamic_neighbors_limit = listen_limit; - return 0; + return 0; } -int -bgp_listen_limit_unset (struct bgp *bgp) +int bgp_listen_limit_unset(struct bgp *bgp) { - if (! bgp) - return -1; + if (!bgp) + return -1; - bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT; + bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT; - return 0; + return 0; } -int -bgp_map_afi_safi_iana2int (iana_afi_t pkt_afi, safi_t pkt_safi, - afi_t *afi, safi_t *safi) +int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, safi_t pkt_safi, afi_t *afi, + safi_t *safi) { - /* Map from IANA values to internal values, return error if - * values are unrecognized. - */ - *afi = afi_iana2int (pkt_afi); - *safi = safi_iana2int (pkt_safi); - if (*afi == AFI_MAX || *safi == SAFI_MAX) - return -1; + /* Map from IANA values to internal values, return error if + * values are unrecognized. + */ + *afi = afi_iana2int(pkt_afi); + *safi = safi_iana2int(pkt_safi); + if (*afi == AFI_MAX || *safi == SAFI_MAX) + return -1; - return 0; + return 0; } -int -bgp_map_afi_safi_int2iana (afi_t afi, safi_t safi, - iana_afi_t *pkt_afi, safi_t *pkt_safi) +int bgp_map_afi_safi_int2iana(afi_t afi, safi_t safi, iana_afi_t *pkt_afi, + safi_t *pkt_safi) { - /* Map from internal values to IANA values, return error if - * internal values are bad (unexpected). - */ - if (afi == AFI_MAX || safi == SAFI_MAX) - return -1; - *pkt_afi = afi_int2iana (afi); - *pkt_safi = safi_int2iana (safi); - return 0; + /* Map from internal values to IANA values, return error if + * internal values are bad (unexpected). + */ + if (afi == AFI_MAX || safi == SAFI_MAX) + return -1; + *pkt_afi = afi_int2iana(afi); + *pkt_safi = safi_int2iana(safi); + return 0; } -struct peer_af * -peer_af_create (struct peer *peer, afi_t afi, safi_t safi) +struct peer_af *peer_af_create(struct peer *peer, afi_t afi, safi_t safi) { - struct peer_af *af; - int afid; + struct peer_af *af; + int afid; - if (!peer) - return NULL; + if (!peer) + return NULL; - afid = afindex(afi, safi); - if (afid >= BGP_AF_MAX) - return NULL; + afid = afindex(afi, safi); + if (afid >= BGP_AF_MAX) + return NULL; - assert(peer->peer_af_array[afid] == NULL); + assert(peer->peer_af_array[afid] == NULL); - /* Allocate new peer af */ - af = XCALLOC (MTYPE_BGP_PEER_AF, sizeof (struct peer_af)); + /* Allocate new peer af */ + af = XCALLOC(MTYPE_BGP_PEER_AF, sizeof(struct peer_af)); - if (af == NULL) - { - zlog_err("Could not create af structure for peer %s", peer->host); - return NULL; - } + if (af == NULL) { + zlog_err("Could not create af structure for peer %s", + peer->host); + return NULL; + } - peer->peer_af_array[afid] = af; - af->afi = afi; - af->safi = safi; - af->afid = afid; - af->peer = peer; + peer->peer_af_array[afid] = af; + af->afi = afi; + af->safi = safi; + af->afid = afid; + af->peer = peer; - return af; + return af; } -struct peer_af * -peer_af_find (struct peer *peer, afi_t afi, safi_t safi) +struct peer_af *peer_af_find(struct peer *peer, afi_t afi, safi_t safi) { - int afid; + int afid; - if (!peer) - return NULL; + if (!peer) + return NULL; - afid = afindex(afi, safi); - if (afid >= BGP_AF_MAX) - return NULL; + afid = afindex(afi, safi); + if (afid >= BGP_AF_MAX) + return NULL; - return peer->peer_af_array[afid]; + return peer->peer_af_array[afid]; } -int -peer_af_delete (struct peer *peer, afi_t afi, safi_t safi) +int peer_af_delete(struct peer *peer, afi_t afi, safi_t safi) { - struct peer_af *af; - int afid; + struct peer_af *af; + int afid; - if (!peer) - return -1; + if (!peer) + return -1; - afid = afindex(afi, safi); - if (afid >= BGP_AF_MAX) - return -1; + afid = afindex(afi, safi); + if (afid >= BGP_AF_MAX) + return -1; - af = peer->peer_af_array[afid]; - if (!af) - return -1; + af = peer->peer_af_array[afid]; + if (!af) + return -1; - bgp_stop_announce_route_timer (af); + bgp_stop_announce_route_timer(af); - if (PAF_SUBGRP(af)) - { - if (BGP_DEBUG (update_groups, UPDATE_GROUPS)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " remove peer %s", - af->subgroup->update_group->id, af->subgroup->id, peer->host); - } + if (PAF_SUBGRP(af)) { + if (BGP_DEBUG(update_groups, UPDATE_GROUPS)) + zlog_debug("u%" PRIu64 ":s%" PRIu64 " remove peer %s", + af->subgroup->update_group->id, + af->subgroup->id, peer->host); + } - update_subgroup_remove_peer (af->subgroup, af); + update_subgroup_remove_peer(af->subgroup, af); - peer->peer_af_array[afid] = NULL; - XFREE(MTYPE_BGP_PEER_AF, af); - return 0; + peer->peer_af_array[afid] = NULL; + XFREE(MTYPE_BGP_PEER_AF, af); + return 0; } /* Peer comparison function for sorting. */ -int -peer_cmp (struct peer *p1, struct peer *p2) +int peer_cmp(struct peer *p1, struct peer *p2) { - if (p1->group && !p2->group) - return -1; + if (p1->group && !p2->group) + return -1; - if (!p1->group && p2->group) - return 1; + if (!p1->group && p2->group) + return 1; - if (p1->group == p2->group) - { - if (p1->conf_if && !p2->conf_if) - return -1; + if (p1->group == p2->group) { + if (p1->conf_if && !p2->conf_if) + return -1; - if (!p1->conf_if && p2->conf_if) - return 1; + if (!p1->conf_if && p2->conf_if) + return 1; - if (p1->conf_if && p2->conf_if) - return if_cmp_name_func (p1->conf_if, p2->conf_if); - } - else - return strcmp (p1->group->name, p2->group->name); + if (p1->conf_if && p2->conf_if) + return if_cmp_name_func(p1->conf_if, p2->conf_if); + } else + return strcmp(p1->group->name, p2->group->name); - return sockunion_cmp (&p1->su, &p2->su); + return sockunion_cmp(&p1->su, &p2->su); } -static unsigned int -peer_hash_key_make(void *p) +static unsigned int peer_hash_key_make(void *p) { - struct peer *peer = p; - return sockunion_hash(&peer->su); + struct peer *peer = p; + return sockunion_hash(&peer->su); } -static int -peer_hash_cmp (const void *p1, const void *p2) +static int peer_hash_cmp(const void *p1, const void *p2) { - const struct peer *peer1 = p1; - const struct peer *peer2 = p2; - return (sockunion_same (&peer1->su, &peer2->su) && - CHECK_FLAG (peer1->flags, PEER_FLAG_CONFIG_NODE) == CHECK_FLAG (peer2->flags, PEER_FLAG_CONFIG_NODE)); + const struct peer *peer1 = p1; + const struct peer *peer2 = p2; + return (sockunion_same(&peer1->su, &peer2->su) + && CHECK_FLAG(peer1->flags, PEER_FLAG_CONFIG_NODE) + == CHECK_FLAG(peer2->flags, PEER_FLAG_CONFIG_NODE)); } -int -peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag) +int peer_af_flag_check(struct peer *peer, afi_t afi, safi_t safi, + u_int32_t flag) { - return CHECK_FLAG (peer->af_flags[afi][safi], flag); + return CHECK_FLAG(peer->af_flags[afi][safi], flag); } /* Return true if flag is set for the peer but not the peer-group */ -static int -peergroup_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag) +static int peergroup_af_flag_check(struct peer *peer, afi_t afi, safi_t safi, + u_int32_t flag) { - struct peer *g_peer = NULL; + struct peer *g_peer = NULL; - if (peer_af_flag_check (peer, afi, safi, flag)) - { - if (peer_group_active (peer)) - { - g_peer = peer->group->conf; + if (peer_af_flag_check(peer, afi, safi, flag)) { + if (peer_group_active(peer)) { + g_peer = peer->group->conf; - /* If this flag is not set for the peer's peer-group then return true */ - if (!peer_af_flag_check (g_peer, afi, safi, flag)) - { - return 1; - } - } + /* If this flag is not set for the peer's peer-group + * then return true */ + if (!peer_af_flag_check(g_peer, afi, safi, flag)) { + return 1; + } + } - /* peer is not in a peer-group but the flag is set to return true */ - else - { - return 1; - } - } + /* peer is not in a peer-group but the flag is set to return + true */ + else { + return 1; + } + } - return 0; + return 0; } /* Reset all address family specific configuration. */ -static void -peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi) +static void peer_af_flag_reset(struct peer *peer, afi_t afi, safi_t safi) { - int i; - struct bgp_filter *filter; - char orf_name[BUFSIZ]; + int i; + struct bgp_filter *filter; + char orf_name[BUFSIZ]; - filter = &peer->filter[afi][safi]; + filter = &peer->filter[afi][safi]; - /* Clear neighbor filter and route-map */ - for (i = FILTER_IN; i < FILTER_MAX; i++) - { - if (filter->dlist[i].name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[i].name); - filter->dlist[i].name = NULL; - } - if (filter->plist[i].name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[i].name); - filter->plist[i].name = NULL; - } - if (filter->aslist[i].name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[i].name); - filter->aslist[i].name = NULL; + /* Clear neighbor filter and route-map */ + for (i = FILTER_IN; i < FILTER_MAX; i++) { + if (filter->dlist[i].name) { + XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[i].name); + filter->dlist[i].name = NULL; + } + if (filter->plist[i].name) { + XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[i].name); + filter->plist[i].name = NULL; + } + if (filter->aslist[i].name) { + XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[i].name); + filter->aslist[i].name = NULL; + } } - } - for (i = RMAP_IN; i < RMAP_MAX; i++) - { - if (filter->map[i].name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->map[i].name); - filter->map[i].name = NULL; + for (i = RMAP_IN; i < RMAP_MAX; i++) { + if (filter->map[i].name) { + XFREE(MTYPE_BGP_FILTER_NAME, filter->map[i].name); + filter->map[i].name = NULL; + } } - } - - /* Clear unsuppress map. */ - if (filter->usmap.name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); - filter->usmap.name = NULL; - filter->usmap.map = NULL; - /* Clear neighbor's all address family flags. */ - peer->af_flags[afi][safi] = 0; + /* Clear unsuppress map. */ + if (filter->usmap.name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); + filter->usmap.name = NULL; + filter->usmap.map = NULL; - /* Clear neighbor's all address family sflags. */ - peer->af_sflags[afi][safi] = 0; + /* Clear neighbor's all address family flags. */ + peer->af_flags[afi][safi] = 0; - /* Clear neighbor's all address family capabilities. */ - peer->af_cap[afi][safi] = 0; + /* Clear neighbor's all address family sflags. */ + peer->af_sflags[afi][safi] = 0; - /* Clear ORF info */ - peer->orf_plist[afi][safi] = NULL; - sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi); - prefix_bgp_orf_remove_all (afi, orf_name); + /* Clear neighbor's all address family capabilities. */ + peer->af_cap[afi][safi] = 0; - /* Set default neighbor send-community. */ - if (! bgp_option_check (BGP_OPT_CONFIG_CISCO)) - { - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY); - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY); - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY); - } + /* Clear ORF info */ + peer->orf_plist[afi][safi] = NULL; + sprintf(orf_name, "%s.%d.%d", peer->host, afi, safi); + prefix_bgp_orf_remove_all(afi, orf_name); + + /* Set default neighbor send-community. */ + if (!bgp_option_check(BGP_OPT_CONFIG_CISCO)) { + SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY); + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SEND_EXT_COMMUNITY); + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SEND_LARGE_COMMUNITY); + } - /* Clear neighbor default_originate_rmap */ - if (peer->default_rmap[afi][safi].name) - XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name); - peer->default_rmap[afi][safi].name = NULL; - peer->default_rmap[afi][safi].map = NULL; + /* Clear neighbor default_originate_rmap */ + if (peer->default_rmap[afi][safi].name) + XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name); + peer->default_rmap[afi][safi].name = NULL; + peer->default_rmap[afi][safi].map = NULL; - /* Clear neighbor maximum-prefix */ - peer->pmax[afi][safi] = 0; - peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT; + /* Clear neighbor maximum-prefix */ + peer->pmax[afi][safi] = 0; + peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT; } /* peer global config reset */ -static void -peer_global_config_reset (struct peer *peer) +static void peer_global_config_reset(struct peer *peer) { - int v6only; + int v6only; - peer->change_local_as = 0; - peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? MAXTTL : 1); - if (peer->update_source) - { - sockunion_free (peer->update_source); - peer->update_source = NULL; - } - if (peer->update_if) - { - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; - } + peer->change_local_as = 0; + peer->ttl = (peer_sort(peer) == BGP_PEER_IBGP ? MAXTTL : 1); + if (peer->update_source) { + sockunion_free(peer->update_source); + peer->update_source = NULL; + } + if (peer->update_if) { + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; + } - if (peer_sort (peer) == BGP_PEER_IBGP) - peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; - else - peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; + if (peer_sort(peer) == BGP_PEER_IBGP) + peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; + else + peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; - /* This is a per-peer specific flag and so we must preserve it */ - v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); + /* This is a per-peer specific flag and so we must preserve it */ + v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); - peer->flags = 0; + peer->flags = 0; - if (v6only) - SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); + if (v6only) + SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); - peer->config = 0; - peer->holdtime = 0; - peer->keepalive = 0; - peer->connect = 0; - peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; + peer->config = 0; + peer->holdtime = 0; + peer->keepalive = 0; + peer->connect = 0; + peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; - /* Reset some other configs back to defaults. */ - peer->v_start = BGP_INIT_START_TIMER; - peer->password = NULL; - peer->local_id = peer->bgp->router_id; - peer->v_holdtime = peer->bgp->default_holdtime; - peer->v_keepalive = peer->bgp->default_keepalive; + /* Reset some other configs back to defaults. */ + peer->v_start = BGP_INIT_START_TIMER; + peer->password = NULL; + peer->local_id = peer->bgp->router_id; + peer->v_holdtime = peer->bgp->default_holdtime; + peer->v_keepalive = peer->bgp->default_keepalive; - bfd_info_free(&(peer->bfd_info)); + bfd_info_free(&(peer->bfd_info)); - /* Set back the CONFIG_NODE flag. */ - SET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE); + /* Set back the CONFIG_NODE flag. */ + SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); } /* Check peer's AS number and determines if this peer is IBGP or EBGP */ -static bgp_peer_sort_t -peer_calc_sort (struct peer *peer) +static bgp_peer_sort_t peer_calc_sort(struct peer *peer) { - struct bgp *bgp; + struct bgp *bgp; - bgp = peer->bgp; + bgp = peer->bgp; - /* Peer-group */ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (peer->as_type == AS_INTERNAL) - return BGP_PEER_IBGP; + /* Peer-group */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (peer->as_type == AS_INTERNAL) + return BGP_PEER_IBGP; - else if (peer->as_type == AS_EXTERNAL) - return BGP_PEER_EBGP; + else if (peer->as_type == AS_EXTERNAL) + return BGP_PEER_EBGP; - else if (peer->as_type == AS_SPECIFIED && peer->as) - return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP); + else if (peer->as_type == AS_SPECIFIED && peer->as) + return (bgp->as == peer->as ? BGP_PEER_IBGP + : BGP_PEER_EBGP); - else - { - struct peer *peer1; - peer1 = listnode_head (peer->group->peer); - - if (peer1) - return peer1->sort; - } - return BGP_PEER_INTERNAL; - } - - /* Normal peer */ - if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION)) - { - if (peer->local_as == 0) - return BGP_PEER_INTERNAL; - - if (peer->local_as == peer->as) - { - if (bgp->as == bgp->confed_id) - { - if (peer->local_as == bgp->as) - return BGP_PEER_IBGP; - else - return BGP_PEER_EBGP; - } - else - { - if (peer->local_as == bgp->confed_id) - return BGP_PEER_EBGP; - else - return BGP_PEER_IBGP; - } - } - - if (bgp_confederation_peers_check (bgp, peer->as)) - return BGP_PEER_CONFED; - - return BGP_PEER_EBGP; - } - else - { - if (peer->as_type != AS_SPECIFIED) - return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP : BGP_PEER_EBGP); - - return (peer->local_as == 0 - ? BGP_PEER_INTERNAL : peer->local_as == peer->as - ? BGP_PEER_IBGP : BGP_PEER_EBGP); - } + else { + struct peer *peer1; + peer1 = listnode_head(peer->group->peer); + + if (peer1) + return peer1->sort; + } + return BGP_PEER_INTERNAL; + } + + /* Normal peer */ + if (bgp && CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) { + if (peer->local_as == 0) + return BGP_PEER_INTERNAL; + + if (peer->local_as == peer->as) { + if (bgp->as == bgp->confed_id) { + if (peer->local_as == bgp->as) + return BGP_PEER_IBGP; + else + return BGP_PEER_EBGP; + } else { + if (peer->local_as == bgp->confed_id) + return BGP_PEER_EBGP; + else + return BGP_PEER_IBGP; + } + } + + if (bgp_confederation_peers_check(bgp, peer->as)) + return BGP_PEER_CONFED; + + return BGP_PEER_EBGP; + } else { + if (peer->as_type != AS_SPECIFIED) + return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP + : BGP_PEER_EBGP); + + return (peer->local_as == 0 + ? BGP_PEER_INTERNAL + : peer->local_as == peer->as ? BGP_PEER_IBGP + : BGP_PEER_EBGP); + } } /* Calculate and cache the peer "sort" */ -bgp_peer_sort_t -peer_sort (struct peer *peer) -{ - peer->sort = peer_calc_sort (peer); - return peer->sort; -} - -static void -peer_free (struct peer *peer) -{ - assert (peer->status == Deleted); - - QOBJ_UNREG (peer); - - /* this /ought/ to have been done already through bgp_stop earlier, - * but just to be sure.. - */ - bgp_timer_set (peer); - BGP_READ_OFF (peer->t_read); - BGP_WRITE_OFF (peer->t_write); - BGP_EVENT_FLUSH (peer); - - /* Free connected nexthop, if present */ - if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) && - !peer_dynamic_neighbor (peer)) - bgp_delete_connected_nexthop (family2afi(peer->su.sa.sa_family), peer); - - XFREE (MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message); - - if (peer->desc) - { - XFREE (MTYPE_PEER_DESC, peer->desc); - peer->desc = NULL; - } - - /* Free allocated host character. */ - if (peer->host) - { - XFREE (MTYPE_BGP_PEER_HOST, peer->host); - peer->host = NULL; - } - - if (peer->domainname) - { - XFREE (MTYPE_BGP_PEER_HOST, peer->domainname); - peer->domainname = NULL; - } - - if (peer->ifname) - { - XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname); - peer->ifname = NULL; - } - - /* Update source configuration. */ - if (peer->update_source) - { - sockunion_free (peer->update_source); - peer->update_source = NULL; - } - - if (peer->update_if) - { - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; - } - - if (peer->notify.data) - XFREE(MTYPE_TMP, peer->notify.data); - memset (&peer->notify, 0, sizeof (struct bgp_notify)); - - if (peer->clear_node_queue) - { - work_queue_free(peer->clear_node_queue); - peer->clear_node_queue = NULL; - } - - bgp_sync_delete (peer); - - if (peer->conf_if) - { - XFREE (MTYPE_PEER_CONF_IF, peer->conf_if); - peer->conf_if = NULL; - } - - bfd_info_free(&(peer->bfd_info)); - - bgp_unlock(peer->bgp); - - memset (peer, 0, sizeof (struct peer)); - - XFREE (MTYPE_BGP_PEER, peer); -} - +bgp_peer_sort_t peer_sort(struct peer *peer) +{ + peer->sort = peer_calc_sort(peer); + return peer->sort; +} + +static void peer_free(struct peer *peer) +{ + assert(peer->status == Deleted); + + QOBJ_UNREG(peer); + + /* this /ought/ to have been done already through bgp_stop earlier, + * but just to be sure.. + */ + bgp_timer_set(peer); + BGP_READ_OFF(peer->t_read); + BGP_WRITE_OFF(peer->t_write); + BGP_EVENT_FLUSH(peer); + + /* Free connected nexthop, if present */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) + && !peer_dynamic_neighbor(peer)) + bgp_delete_connected_nexthop(family2afi(peer->su.sa.sa_family), + peer); + + XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message); + + if (peer->desc) { + XFREE(MTYPE_PEER_DESC, peer->desc); + peer->desc = NULL; + } + + /* Free allocated host character. */ + if (peer->host) { + XFREE(MTYPE_BGP_PEER_HOST, peer->host); + peer->host = NULL; + } + + if (peer->domainname) { + XFREE(MTYPE_BGP_PEER_HOST, peer->domainname); + peer->domainname = NULL; + } + + if (peer->ifname) { + XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname); + peer->ifname = NULL; + } + + /* Update source configuration. */ + if (peer->update_source) { + sockunion_free(peer->update_source); + peer->update_source = NULL; + } + + if (peer->update_if) { + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; + } + + if (peer->notify.data) + XFREE(MTYPE_TMP, peer->notify.data); + memset(&peer->notify, 0, sizeof(struct bgp_notify)); + + if (peer->clear_node_queue) { + work_queue_free(peer->clear_node_queue); + peer->clear_node_queue = NULL; + } + + bgp_sync_delete(peer); + + if (peer->conf_if) { + XFREE(MTYPE_PEER_CONF_IF, peer->conf_if); + peer->conf_if = NULL; + } + + bfd_info_free(&(peer->bfd_info)); + + bgp_unlock(peer->bgp); + + memset(peer, 0, sizeof(struct peer)); + + XFREE(MTYPE_BGP_PEER, peer); +} + /* increase reference count on a struct peer */ -struct peer * -peer_lock_with_caller (const char *name, struct peer *peer) +struct peer *peer_lock_with_caller(const char *name, struct peer *peer) { - assert (peer && (peer->lock >= 0)); + assert(peer && (peer->lock >= 0)); #if 0 zlog_debug("%s peer_lock %p %d", name, peer, peer->lock); #endif - - peer->lock++; - - return peer; + + peer->lock++; + + return peer; } /* decrease reference count on a struct peer * struct peer is freed and NULL returned if last reference */ -struct peer * -peer_unlock_with_caller (const char *name, struct peer *peer) +struct peer *peer_unlock_with_caller(const char *name, struct peer *peer) { - assert (peer && (peer->lock > 0)); + assert(peer && (peer->lock > 0)); #if 0 zlog_debug("%s peer_unlock %p %d", name, peer, peer->lock); #endif - - peer->lock--; - - if (peer->lock == 0) - { - peer_free (peer); - return NULL; - } - return peer; + peer->lock--; + + if (peer->lock == 0) { + peer_free(peer); + return NULL; + } + + return peer; } /* Allocate new peer object, implicitely locked. */ -struct peer * -peer_new (struct bgp *bgp) -{ - afi_t afi; - safi_t safi; - struct peer *peer; - struct servent *sp; - - /* bgp argument is absolutely required */ - assert (bgp); - if (!bgp) - return NULL; - - /* Allocate new peer. */ - peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer)); - - /* Set default value. */ - peer->fd = -1; - peer->v_start = BGP_INIT_START_TIMER; - peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; - peer->status = Idle; - peer->ostatus = Idle; - peer->cur_event = peer->last_event = peer->last_major_event = 0; - peer->bgp = bgp; - peer = peer_lock (peer); /* initial reference */ - bgp_lock (bgp); - peer->password = NULL; - - /* Set default flags. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - if (! bgp_option_check (BGP_OPT_CONFIG_CISCO)) - { - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY); - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY); - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY); - } - peer->orf_plist[afi][safi] = NULL; - } - SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN); +struct peer *peer_new(struct bgp *bgp) +{ + afi_t afi; + safi_t safi; + struct peer *peer; + struct servent *sp; + + /* bgp argument is absolutely required */ + assert(bgp); + if (!bgp) + return NULL; + + /* Allocate new peer. */ + peer = XCALLOC(MTYPE_BGP_PEER, sizeof(struct peer)); + + /* Set default value. */ + peer->fd = -1; + peer->v_start = BGP_INIT_START_TIMER; + peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; + peer->status = Idle; + peer->ostatus = Idle; + peer->cur_event = peer->last_event = peer->last_major_event = 0; + peer->bgp = bgp; + peer = peer_lock(peer); /* initial reference */ + bgp_lock(bgp); + peer->password = NULL; + + /* Set default flags. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + if (!bgp_option_check(BGP_OPT_CONFIG_CISCO)) { + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SEND_COMMUNITY); + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SEND_EXT_COMMUNITY); + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SEND_LARGE_COMMUNITY); + } + peer->orf_plist[afi][safi] = NULL; + } + SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN); - /* Create buffers. */ - peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE); - peer->obuf = stream_fifo_new (); + /* Create buffers. */ + peer->ibuf = stream_new(BGP_MAX_PACKET_SIZE); + peer->obuf = stream_fifo_new(); - /* We use a larger buffer for peer->work in the event that: - * - We RX a BGP_UPDATE where the attributes alone are just - * under BGP_MAX_PACKET_SIZE - * - The user configures an outbound route-map that does many as-path - * prepends or adds many communities. At most they can have CMD_ARGC_MAX - * args in a route-map so there is a finite limit on how large they can - * make the attributes. - * - * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid bounds - * checking for every single attribute as we construct an UPDATE. - */ - peer->work = stream_new (BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW); - peer->scratch = stream_new (BGP_MAX_PACKET_SIZE); + /* We use a larger buffer for peer->work in the event that: + * - We RX a BGP_UPDATE where the attributes alone are just + * under BGP_MAX_PACKET_SIZE + * - The user configures an outbound route-map that does many as-path + * prepends or adds many communities. At most they can have + * CMD_ARGC_MAX + * args in a route-map so there is a finite limit on how large they + * can + * make the attributes. + * + * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid + * bounds + * checking for every single attribute as we construct an UPDATE. + */ + peer->work = + stream_new(BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW); + peer->scratch = stream_new(BGP_MAX_PACKET_SIZE); - bgp_sync_init (peer); + bgp_sync_init(peer); - /* Get service port number. */ - sp = getservbyname ("bgp", "tcp"); - peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port); + /* Get service port number. */ + sp = getservbyname("bgp", "tcp"); + peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs(sp->s_port); - QOBJ_REG (peer, peer); - return peer; + QOBJ_REG(peer, peer); + return peer; } /* @@ -1259,168 +1174,165 @@ peer_new (struct bgp *bgp) * a neighbor is being deleted. If this about-to-be-deleted structure is * the one with all the config, then we have to copy over the info. */ -void -peer_xfer_config (struct peer *peer_dst, struct peer *peer_src) -{ - struct peer_af *paf; - afi_t afi; - safi_t safi; - int afidx; - - assert(peer_src); - assert(peer_dst); - - /* The following function is used by both peer group config copy to - * individual peer and when we transfer config - */ - if (peer_src->change_local_as) - peer_dst->change_local_as = peer_src->change_local_as; - - /* peer flags apply */ - peer_dst->flags = peer_src->flags; - peer_dst->cap = peer_src->cap; - peer_dst->config = peer_src->config; - - peer_dst->local_as = peer_src->local_as; - peer_dst->ifindex = peer_src->ifindex; - peer_dst->port = peer_src->port; - peer_sort(peer_dst); - peer_dst->rmap_type = peer_src->rmap_type; - - /* Timers */ - peer_dst->holdtime = peer_src->holdtime; - peer_dst->keepalive = peer_src->keepalive; - peer_dst->connect = peer_src->connect; - peer_dst->v_holdtime = peer_src->v_holdtime; - peer_dst->v_keepalive = peer_src->v_keepalive; - peer_dst->routeadv = peer_src->routeadv; - peer_dst->v_routeadv = peer_src->v_routeadv; - - /* password apply */ - if (peer_src->password && !peer_dst->password) - peer_dst->password = XSTRDUP (MTYPE_PEER_PASSWORD, peer_src->password); - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - peer_dst->afc[afi][safi] = peer_src->afc[afi][safi]; - peer_dst->af_flags[afi][safi] = peer_src->af_flags[afi][safi]; - peer_dst->allowas_in[afi][safi] = peer_src->allowas_in[afi][safi]; - peer_dst->weight[afi][safi] = peer_src->weight[afi][safi]; - } - - for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) - { - paf = peer_src->peer_af_array[afidx]; - if (paf != NULL) - peer_af_create(peer_dst, paf->afi, paf->safi); - } - - /* update-source apply */ - if (peer_src->update_source) - { - if (peer_dst->update_source) - sockunion_free (peer_dst->update_source); - if (peer_dst->update_if) - { - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if); - peer_dst->update_if = NULL; - } - peer_dst->update_source = sockunion_dup (peer_src->update_source); - } - else if (peer_src->update_if) - { - if (peer_dst->update_if) - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if); - if (peer_dst->update_source) - { - sockunion_free (peer_dst->update_source); - peer_dst->update_source = NULL; - } - peer_dst->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, peer_src->update_if); - } - - if (peer_src->ifname) - { - if (peer_dst->ifname) - XFREE(MTYPE_BGP_PEER_IFNAME, peer_dst->ifname); - - peer_dst->ifname = XSTRDUP(MTYPE_BGP_PEER_IFNAME, peer_src->ifname); - } -} - -static int -bgp_peer_conf_if_to_su_update_v4 (struct peer *peer, struct interface *ifp) -{ - struct connected *ifc; - struct prefix p; - u_int32_t addr; - struct listnode *node; - - /* If our IPv4 address on the interface is /30 or /31, we can derive the - * IPv4 address of the other end. - */ - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) - { - if (ifc->address && (ifc->address->family == AF_INET)) - { - PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); - if (p.prefixlen == 30) - { - peer->su.sa.sa_family = AF_INET; - addr = ntohl(p.u.prefix4.s_addr); - if (addr % 4 == 1) - peer->su.sin.sin_addr.s_addr = htonl(addr+1); - else if (addr % 4 == 2) - peer->su.sin.sin_addr.s_addr = htonl(addr-1); +void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src) +{ + struct peer_af *paf; + afi_t afi; + safi_t safi; + int afidx; + + assert(peer_src); + assert(peer_dst); + + /* The following function is used by both peer group config copy to + * individual peer and when we transfer config + */ + if (peer_src->change_local_as) + peer_dst->change_local_as = peer_src->change_local_as; + + /* peer flags apply */ + peer_dst->flags = peer_src->flags; + peer_dst->cap = peer_src->cap; + peer_dst->config = peer_src->config; + + peer_dst->local_as = peer_src->local_as; + peer_dst->ifindex = peer_src->ifindex; + peer_dst->port = peer_src->port; + peer_sort(peer_dst); + peer_dst->rmap_type = peer_src->rmap_type; + + /* Timers */ + peer_dst->holdtime = peer_src->holdtime; + peer_dst->keepalive = peer_src->keepalive; + peer_dst->connect = peer_src->connect; + peer_dst->v_holdtime = peer_src->v_holdtime; + peer_dst->v_keepalive = peer_src->v_keepalive; + peer_dst->routeadv = peer_src->routeadv; + peer_dst->v_routeadv = peer_src->v_routeadv; + + /* password apply */ + if (peer_src->password && !peer_dst->password) + peer_dst->password = + XSTRDUP(MTYPE_PEER_PASSWORD, peer_src->password); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + peer_dst->afc[afi][safi] = peer_src->afc[afi][safi]; + peer_dst->af_flags[afi][safi] = + peer_src->af_flags[afi][safi]; + peer_dst->allowas_in[afi][safi] = + peer_src->allowas_in[afi][safi]; + peer_dst->weight[afi][safi] = + peer_src->weight[afi][safi]; + } + + for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) { + paf = peer_src->peer_af_array[afidx]; + if (paf != NULL) + peer_af_create(peer_dst, paf->afi, paf->safi); + } + + /* update-source apply */ + if (peer_src->update_source) { + if (peer_dst->update_source) + sockunion_free(peer_dst->update_source); + if (peer_dst->update_if) { + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if); + peer_dst->update_if = NULL; + } + peer_dst->update_source = + sockunion_dup(peer_src->update_source); + } else if (peer_src->update_if) { + if (peer_dst->update_if) + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if); + if (peer_dst->update_source) { + sockunion_free(peer_dst->update_source); + peer_dst->update_source = NULL; + } + peer_dst->update_if = + XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, peer_src->update_if); + } + + if (peer_src->ifname) { + if (peer_dst->ifname) + XFREE(MTYPE_BGP_PEER_IFNAME, peer_dst->ifname); + + peer_dst->ifname = + XSTRDUP(MTYPE_BGP_PEER_IFNAME, peer_src->ifname); + } +} + +static int bgp_peer_conf_if_to_su_update_v4(struct peer *peer, + struct interface *ifp) +{ + struct connected *ifc; + struct prefix p; + u_int32_t addr; + struct listnode *node; + + /* If our IPv4 address on the interface is /30 or /31, we can derive the + * IPv4 address of the other end. + */ + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { + if (ifc->address && (ifc->address->family == AF_INET)) { + PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); + if (p.prefixlen == 30) { + peer->su.sa.sa_family = AF_INET; + addr = ntohl(p.u.prefix4.s_addr); + if (addr % 4 == 1) + peer->su.sin.sin_addr.s_addr = + htonl(addr + 1); + else if (addr % 4 == 2) + peer->su.sin.sin_addr.s_addr = + htonl(addr - 1); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - peer->su.sin.sin_len = sizeof(struct sockaddr_in); + peer->su.sin.sin_len = + sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - return 1; - } - else if (p.prefixlen == 31) - { - peer->su.sa.sa_family = AF_INET; - addr = ntohl(p.u.prefix4.s_addr); - if (addr % 2 == 0) - peer->su.sin.sin_addr.s_addr = htonl(addr+1); - else - peer->su.sin.sin_addr.s_addr = htonl(addr-1); + return 1; + } else if (p.prefixlen == 31) { + peer->su.sa.sa_family = AF_INET; + addr = ntohl(p.u.prefix4.s_addr); + if (addr % 2 == 0) + peer->su.sin.sin_addr.s_addr = + htonl(addr + 1); + else + peer->su.sin.sin_addr.s_addr = + htonl(addr - 1); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - peer->su.sin.sin_len = sizeof(struct sockaddr_in); + peer->su.sin.sin_len = + sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - return 1; - } - else - if (bgp_debug_neighbor_events(peer)) - zlog_debug("%s: IPv4 interface address is not /30 or /31, v4 session not started", - peer->conf_if); - } - } - - return 0; -} - -static int -bgp_peer_conf_if_to_su_update_v6 (struct peer *peer, struct interface *ifp) -{ - struct nbr_connected *ifc_nbr; - - /* Have we learnt the peer's IPv6 link-local address? */ - if (ifp->nbr_connected && - (ifc_nbr = listnode_head(ifp->nbr_connected))) - { - peer->su.sa.sa_family = AF_INET6; - memcpy(&peer->su.sin6.sin6_addr, &ifc_nbr->address->u.prefix, - sizeof (struct in6_addr)); + return 1; + } else if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s: IPv4 interface address is not /30 or /31, v4 session not started", + peer->conf_if); + } + } + + return 0; +} + +static int bgp_peer_conf_if_to_su_update_v6(struct peer *peer, + struct interface *ifp) +{ + struct nbr_connected *ifc_nbr; + + /* Have we learnt the peer's IPv6 link-local address? */ + if (ifp->nbr_connected + && (ifc_nbr = listnode_head(ifp->nbr_connected))) { + peer->su.sa.sa_family = AF_INET6; + memcpy(&peer->su.sin6.sin6_addr, &ifc_nbr->address->u.prefix, + sizeof(struct in6_addr)); #ifdef SIN6_LEN - peer->su.sin6.sin6_len = sizeof (struct sockaddr_in6); + peer->su.sin6.sin6_len = sizeof(struct sockaddr_in6); #endif - peer->su.sin6.sin6_scope_id = ifp->ifindex; - return 1; - } + peer->su.sin6.sin6_scope_id = ifp->ifindex; + return 1; + } - return 0; + return 0; } /* @@ -1428,567 +1340,525 @@ bgp_peer_conf_if_to_su_update_v6 (struct peer *peer, struct interface *ifp) * learnt/derived peer address. If the address has changed, update the * password on the listen socket, if needed. */ -void -bgp_peer_conf_if_to_su_update (struct peer *peer) -{ - struct interface *ifp; - int prev_family; - int peer_addr_updated = 0; - - if (!peer->conf_if) - return; - - prev_family = peer->su.sa.sa_family; - if ((ifp = if_lookup_by_name (peer->conf_if, peer->bgp->vrf_id))) - { - peer->ifp = ifp; - /* If BGP unnumbered is not "v6only", we first see if we can derive the - * peer's IPv4 address. - */ - if (!CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) - peer_addr_updated = bgp_peer_conf_if_to_su_update_v4 (peer, ifp); - - /* If "v6only" or we can't derive peer's IPv4 address, see if we've - * learnt the peer's IPv6 link-local address. This is from the source - * IPv6 address in router advertisement. - */ - if (!peer_addr_updated) - peer_addr_updated = bgp_peer_conf_if_to_su_update_v6 (peer, ifp); - } - /* If we could derive the peer address, we may need to install the password - * configured for the peer, if any, on the listen socket. Otherwise, mark - * that peer's address is not available and uninstall the password, if - * needed. - */ - if (peer_addr_updated) - { - if (peer->password && prev_family == AF_UNSPEC) - bgp_md5_set (peer); - } - else - { - if (peer->password && prev_family != AF_UNSPEC) - bgp_md5_unset (peer); - peer->su.sa.sa_family = AF_UNSPEC; - memset(&peer->su.sin6.sin6_addr, 0, sizeof (struct in6_addr)); - } - - /* Since our su changed we need to del/add peer to the peerhash */ - hash_release(peer->bgp->peerhash, peer); - hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); +void bgp_peer_conf_if_to_su_update(struct peer *peer) +{ + struct interface *ifp; + int prev_family; + int peer_addr_updated = 0; + + if (!peer->conf_if) + return; + + prev_family = peer->su.sa.sa_family; + if ((ifp = if_lookup_by_name(peer->conf_if, peer->bgp->vrf_id))) { + peer->ifp = ifp; + /* If BGP unnumbered is not "v6only", we first see if we can + * derive the + * peer's IPv4 address. + */ + if (!CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) + peer_addr_updated = + bgp_peer_conf_if_to_su_update_v4(peer, ifp); + + /* If "v6only" or we can't derive peer's IPv4 address, see if + * we've + * learnt the peer's IPv6 link-local address. This is from the + * source + * IPv6 address in router advertisement. + */ + if (!peer_addr_updated) + peer_addr_updated = + bgp_peer_conf_if_to_su_update_v6(peer, ifp); + } + /* If we could derive the peer address, we may need to install the + * password + * configured for the peer, if any, on the listen socket. Otherwise, + * mark + * that peer's address is not available and uninstall the password, if + * needed. + */ + if (peer_addr_updated) { + if (peer->password && prev_family == AF_UNSPEC) + bgp_md5_set(peer); + } else { + if (peer->password && prev_family != AF_UNSPEC) + bgp_md5_unset(peer); + peer->su.sa.sa_family = AF_UNSPEC; + memset(&peer->su.sin6.sin6_addr, 0, sizeof(struct in6_addr)); + } + + /* Since our su changed we need to del/add peer to the peerhash */ + hash_release(peer->bgp->peerhash, peer); + hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); } /* Force a bestpath recalculation for all prefixes. This is used * when 'bgp bestpath' commands are entered. */ -void -bgp_recalculate_all_bestpaths (struct bgp *bgp) -{ - afi_t afi; - safi_t safi; - struct bgp_node *rn, *nrn; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - for (rn = bgp_table_top (bgp->rib[afi][safi]); rn; - rn = bgp_route_next (rn)) - { - if (rn->info != NULL) - { - /* Special handling for 2-level routing tables. */ - if (safi == SAFI_MPLS_VPN || - safi == SAFI_ENCAP || - safi == SAFI_EVPN) - { - for (nrn = bgp_table_top((struct bgp_table *)(rn->info)); - nrn; nrn = bgp_route_next (nrn)) - bgp_process (bgp, nrn, afi, safi); - } - else - bgp_process (bgp, rn, afi, safi); - } - } - } - } +void bgp_recalculate_all_bestpaths(struct bgp *bgp) +{ + afi_t afi; + safi_t safi; + struct bgp_node *rn, *nrn; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; + rn = bgp_route_next(rn)) { + if (rn->info != NULL) { + /* Special handling for 2-level routing + * tables. */ + if (safi == SAFI_MPLS_VPN + || safi == SAFI_ENCAP + || safi == SAFI_EVPN) { + for (nrn = bgp_table_top(( + struct bgp_table + *)(rn->info)); + nrn; + nrn = bgp_route_next(nrn)) + bgp_process(bgp, nrn, + afi, safi); + } else + bgp_process(bgp, rn, afi, safi); + } + } + } + } } /* Create new BGP peer. */ -struct peer * -peer_create (union sockunion *su, const char *conf_if, struct bgp *bgp, - as_t local_as, as_t remote_as, int as_type, afi_t afi, safi_t safi, struct peer_group *group) -{ - int active; - struct peer *peer; - char buf[SU_ADDRSTRLEN]; - - peer = peer_new (bgp); - if (conf_if) - { - peer->conf_if = XSTRDUP (MTYPE_PEER_CONF_IF, conf_if); - bgp_peer_conf_if_to_su_update(peer); - if (peer->host) - XFREE(MTYPE_BGP_PEER_HOST, peer->host); - peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, conf_if); - } - else if (su) - { - peer->su = *su; - sockunion2str (su, buf, SU_ADDRSTRLEN); - if (peer->host) - XFREE(MTYPE_BGP_PEER_HOST, peer->host); - peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf); - } - peer->local_as = local_as; - peer->as = remote_as; - peer->as_type = as_type; - peer->local_id = bgp->router_id; - peer->v_holdtime = bgp->default_holdtime; - peer->v_keepalive = bgp->default_keepalive; - if (peer_sort (peer) == BGP_PEER_IBGP) - peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; - else - peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; - - peer = peer_lock (peer); /* bgp peer list reference */ - peer->group = group; - listnode_add_sort (bgp->peer, peer); - hash_get(bgp->peerhash, peer, hash_alloc_intern); - - active = peer_active (peer); - - /* Last read and reset time set */ - peer->readtime = peer->resettime = bgp_clock (); - - /* Default TTL set. */ - peer->ttl = (peer->sort == BGP_PEER_IBGP) ? MAXTTL : 1; - - SET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE); - - if (afi && safi) - { - peer->afc[afi][safi] = 1; - peer_af_create(peer, afi, safi); - } - - /* Set up peer's events and timers. */ - if (! active && peer_active (peer)) - bgp_timer_set (peer); - - return peer; +struct peer *peer_create(union sockunion *su, const char *conf_if, + struct bgp *bgp, as_t local_as, as_t remote_as, + int as_type, afi_t afi, safi_t safi, + struct peer_group *group) +{ + int active; + struct peer *peer; + char buf[SU_ADDRSTRLEN]; + + peer = peer_new(bgp); + if (conf_if) { + peer->conf_if = XSTRDUP(MTYPE_PEER_CONF_IF, conf_if); + bgp_peer_conf_if_to_su_update(peer); + if (peer->host) + XFREE(MTYPE_BGP_PEER_HOST, peer->host); + peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, conf_if); + } else if (su) { + peer->su = *su; + sockunion2str(su, buf, SU_ADDRSTRLEN); + if (peer->host) + XFREE(MTYPE_BGP_PEER_HOST, peer->host); + peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, buf); + } + peer->local_as = local_as; + peer->as = remote_as; + peer->as_type = as_type; + peer->local_id = bgp->router_id; + peer->v_holdtime = bgp->default_holdtime; + peer->v_keepalive = bgp->default_keepalive; + if (peer_sort(peer) == BGP_PEER_IBGP) + peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; + else + peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; + + peer = peer_lock(peer); /* bgp peer list reference */ + peer->group = group; + listnode_add_sort(bgp->peer, peer); + hash_get(bgp->peerhash, peer, hash_alloc_intern); + + active = peer_active(peer); + + /* Last read and reset time set */ + peer->readtime = peer->resettime = bgp_clock(); + + /* Default TTL set. */ + peer->ttl = (peer->sort == BGP_PEER_IBGP) ? MAXTTL : 1; + + SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); + + if (afi && safi) { + peer->afc[afi][safi] = 1; + peer_af_create(peer, afi, safi); + } + + /* Set up peer's events and timers. */ + if (!active && peer_active(peer)) + bgp_timer_set(peer); + + return peer; } /* Make accept BGP peer. This function is only called from the test code */ -struct peer * -peer_create_accept (struct bgp *bgp) +struct peer *peer_create_accept(struct bgp *bgp) { - struct peer *peer; + struct peer *peer; - peer = peer_new (bgp); + peer = peer_new(bgp); - peer = peer_lock (peer); /* bgp peer list reference */ - listnode_add_sort (bgp->peer, peer); + peer = peer_lock(peer); /* bgp peer list reference */ + listnode_add_sort(bgp->peer, peer); - return peer; + return peer; } /* Change peer's AS number. */ -void -peer_as_change (struct peer *peer, as_t as, int as_specified) -{ - bgp_peer_sort_t type; - struct peer *conf; - - /* Stop peer. */ - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - } - type = peer_sort (peer); - peer->as = as; - peer->as_type = as_specified; - - if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION) - && ! bgp_confederation_peers_check (peer->bgp, as) - && peer->bgp->as != as) - peer->local_as = peer->bgp->confed_id; - else - peer->local_as = peer->bgp->as; - - /* Advertisement-interval reset */ - conf = NULL; - if (peer->group) - conf = peer->group->conf; - - if (conf && CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV)) - { - peer->v_routeadv = conf->routeadv; - } - /* Only go back to the default advertisement-interval if the user had not - * already configured it */ - else if (!CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV)) - { - if (peer_sort (peer) == BGP_PEER_IBGP) - peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; - else - peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; - } - /* TTL reset */ - if (peer_sort (peer) == BGP_PEER_IBGP) - peer->ttl = MAXTTL; - else if (type == BGP_PEER_IBGP) - peer->ttl = 1; - - /* reflector-client reset */ - if (peer_sort (peer) != BGP_PEER_IBGP) - { - UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_LABELED_UNICAST], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_ENCAP], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_LABELED_UNICAST], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_L2VPN][SAFI_EVPN], - PEER_FLAG_REFLECTOR_CLIENT); - } - - /* local-as reset */ - if (peer_sort (peer) != BGP_PEER_EBGP) - { - peer->change_local_as = 0; - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); - } +void peer_as_change(struct peer *peer, as_t as, int as_specified) +{ + bgp_peer_sort_t type; + struct peer *conf; + + /* Stop peer. */ + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + } + type = peer_sort(peer); + peer->as = as; + peer->as_type = as_specified; + + if (bgp_config_check(peer->bgp, BGP_CONFIG_CONFEDERATION) + && !bgp_confederation_peers_check(peer->bgp, as) + && peer->bgp->as != as) + peer->local_as = peer->bgp->confed_id; + else + peer->local_as = peer->bgp->as; + + /* Advertisement-interval reset */ + conf = NULL; + if (peer->group) + conf = peer->group->conf; + + if (conf && CHECK_FLAG(conf->config, PEER_CONFIG_ROUTEADV)) { + peer->v_routeadv = conf->routeadv; + } + /* Only go back to the default advertisement-interval if the user had + * not + * already configured it */ + else if (!CHECK_FLAG(peer->config, PEER_CONFIG_ROUTEADV)) { + if (peer_sort(peer) == BGP_PEER_IBGP) + peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; + else + peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; + } + /* TTL reset */ + if (peer_sort(peer) == BGP_PEER_IBGP) + peer->ttl = MAXTTL; + else if (type == BGP_PEER_IBGP) + peer->ttl = 1; + + /* reflector-client reset */ + if (peer_sort(peer) != BGP_PEER_IBGP) { + UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_UNICAST], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_MULTICAST], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_LABELED_UNICAST], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_MPLS_VPN], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_ENCAP], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_UNICAST], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_MULTICAST], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_LABELED_UNICAST], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_MPLS_VPN], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_ENCAP], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_L2VPN][SAFI_EVPN], + PEER_FLAG_REFLECTOR_CLIENT); + } + + /* local-as reset */ + if (peer_sort(peer) != BGP_PEER_EBGP) { + peer->change_local_as = 0; + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); + } } /* If peer does not exist, create new one. If peer already exists, set AS number to the peer. */ -int -peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if, - as_t *as, int as_type, afi_t afi, safi_t safi) -{ - struct peer *peer; - as_t local_as; - - if (conf_if) - peer = peer_lookup_by_conf_if (bgp, conf_if); - else - peer = peer_lookup (bgp, su); - - if (peer) - { - /* Not allowed for a dynamic peer. */ - if (peer_dynamic_neighbor (peer)) - { - *as = peer->as; - return BGP_ERR_INVALID_FOR_DYNAMIC_PEER; - } - - /* When this peer is a member of peer-group. */ - if (peer->group) - { - if (peer->group->conf->as) - { - /* Return peer group's AS number. */ - *as = peer->group->conf->as; - return BGP_ERR_PEER_GROUP_MEMBER; - } - if (peer_sort (peer->group->conf) == BGP_PEER_IBGP) - { - if ((as_type != AS_INTERNAL) && (bgp->as != *as)) - { - *as = peer->as; - return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT; - } - } - else - { - if ((as_type != AS_EXTERNAL) && (bgp->as == *as)) - { - *as = peer->as; - return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT; - } - } - } - - /* Existing peer's AS number change. */ - if (((peer->as_type == AS_SPECIFIED) && peer->as != *as) || - (peer->as_type != as_type)) - peer_as_change (peer, *as, as_type); - } - else - { - if (conf_if) - return BGP_ERR_NO_INTERFACE_CONFIG; - - /* If the peer is not part of our confederation, and its not an - iBGP peer then spoof the source AS */ - if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION) - && ! bgp_confederation_peers_check (bgp, *as) - && bgp->as != *as) - local_as = bgp->confed_id; - else - local_as = bgp->as; - - /* If this is IPv4 unicast configuration and "no bgp default - ipv4-unicast" is specified. */ - - if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4) - && afi == AFI_IP && safi == SAFI_UNICAST) - peer_create (su, conf_if, bgp, local_as, *as, as_type, 0, 0, NULL); - else - peer_create (su, conf_if, bgp, local_as, *as, as_type, afi, safi, NULL); - } - - return 0; -} - -static int -non_peergroup_activate_af (struct peer *peer, afi_t afi, safi_t safi) -{ - int active; - - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - zlog_err("%s was called for peer-group %s", __func__, peer->host); - return 1; - } - - /* Do not activate a peer for both SAFI_UNICAST and SAFI_LABELED_UNICAST */ - if ((safi == SAFI_UNICAST && peer->afc[afi][SAFI_LABELED_UNICAST]) || - (safi == SAFI_LABELED_UNICAST && peer->afc[afi][SAFI_UNICAST])) - return BGP_ERR_PEER_SAFI_CONFLICT; - - /* Nothing to do if we've already activated this peer */ - if (peer->afc[afi][safi]) - return 0; - - if (peer_af_create(peer, afi, safi) == NULL) - return 1; - - active = peer_active (peer); - peer->afc[afi][safi] = 1; - - if (!active && peer_active (peer)) - { - bgp_timer_set (peer); - } - else - { - if (peer->status == Established) - { - if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV)) - { - peer->afc_adv[afi][safi] = 1; - bgp_capability_send (peer, afi, safi, - CAPABILITY_CODE_MP, - CAPABILITY_ACTION_SET); - if (peer->afc_recv[afi][safi]) - { - peer->afc_nego[afi][safi] = 1; - bgp_announce_route (peer, afi, safi); - } - } - else - { - peer->last_reset = PEER_DOWN_AF_ACTIVATE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - } - } - - return 0; +int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if, + as_t *as, int as_type, afi_t afi, safi_t safi) +{ + struct peer *peer; + as_t local_as; + + if (conf_if) + peer = peer_lookup_by_conf_if(bgp, conf_if); + else + peer = peer_lookup(bgp, su); + + if (peer) { + /* Not allowed for a dynamic peer. */ + if (peer_dynamic_neighbor(peer)) { + *as = peer->as; + return BGP_ERR_INVALID_FOR_DYNAMIC_PEER; + } + + /* When this peer is a member of peer-group. */ + if (peer->group) { + if (peer->group->conf->as) { + /* Return peer group's AS number. */ + *as = peer->group->conf->as; + return BGP_ERR_PEER_GROUP_MEMBER; + } + if (peer_sort(peer->group->conf) == BGP_PEER_IBGP) { + if ((as_type != AS_INTERNAL) + && (bgp->as != *as)) { + *as = peer->as; + return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT; + } + } else { + if ((as_type != AS_EXTERNAL) + && (bgp->as == *as)) { + *as = peer->as; + return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT; + } + } + } + + /* Existing peer's AS number change. */ + if (((peer->as_type == AS_SPECIFIED) && peer->as != *as) + || (peer->as_type != as_type)) + peer_as_change(peer, *as, as_type); + } else { + if (conf_if) + return BGP_ERR_NO_INTERFACE_CONFIG; + + /* If the peer is not part of our confederation, and its not an + iBGP peer then spoof the source AS */ + if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION) + && !bgp_confederation_peers_check(bgp, *as) + && bgp->as != *as) + local_as = bgp->confed_id; + else + local_as = bgp->as; + + /* If this is IPv4 unicast configuration and "no bgp default + ipv4-unicast" is specified. */ + + if (bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4) + && afi == AFI_IP && safi == SAFI_UNICAST) + peer_create(su, conf_if, bgp, local_as, *as, as_type, 0, + 0, NULL); + else + peer_create(su, conf_if, bgp, local_as, *as, as_type, + afi, safi, NULL); + } + + return 0; +} + +static int non_peergroup_activate_af(struct peer *peer, afi_t afi, safi_t safi) +{ + int active; + + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + zlog_err("%s was called for peer-group %s", __func__, + peer->host); + return 1; + } + + /* Do not activate a peer for both SAFI_UNICAST and SAFI_LABELED_UNICAST + */ + if ((safi == SAFI_UNICAST && peer->afc[afi][SAFI_LABELED_UNICAST]) + || (safi == SAFI_LABELED_UNICAST && peer->afc[afi][SAFI_UNICAST])) + return BGP_ERR_PEER_SAFI_CONFLICT; + + /* Nothing to do if we've already activated this peer */ + if (peer->afc[afi][safi]) + return 0; + + if (peer_af_create(peer, afi, safi) == NULL) + return 1; + + active = peer_active(peer); + peer->afc[afi][safi] = 1; + + if (!active && peer_active(peer)) { + bgp_timer_set(peer); + } else { + if (peer->status == Established) { + if (CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV)) { + peer->afc_adv[afi][safi] = 1; + bgp_capability_send(peer, afi, safi, + CAPABILITY_CODE_MP, + CAPABILITY_ACTION_SET); + if (peer->afc_recv[afi][safi]) { + peer->afc_nego[afi][safi] = 1; + bgp_announce_route(peer, afi, safi); + } + } else { + peer->last_reset = PEER_DOWN_AF_ACTIVATE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } + } + } + + return 0; } /* Activate the peer or peer group for specified AFI and SAFI. */ -int -peer_activate (struct peer *peer, afi_t afi, safi_t safi) -{ - int ret = 0; - struct peer_group *group; - struct listnode *node, *nnode; - struct peer *tmp_peer; - - /* Nothing to do if we've already activated this peer */ - if (peer->afc[afi][safi]) - return ret; - - /* This is a peer-group so activate all of the members of the - * peer-group as well */ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - - /* Do not activate a peer for both SAFI_UNICAST and SAFI_LABELED_UNICAST */ - if ((safi == SAFI_UNICAST && peer->afc[afi][SAFI_LABELED_UNICAST]) || - (safi == SAFI_LABELED_UNICAST && peer->afc[afi][SAFI_UNICAST])) - return BGP_ERR_PEER_SAFI_CONFLICT; - - peer->afc[afi][safi] = 1; - group = peer->group; - - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer)) - { - ret |= non_peergroup_activate_af (tmp_peer, afi, safi); - } - } - else - { - ret |= non_peergroup_activate_af (peer, afi, safi); - } - - return ret; -} - -static int -non_peergroup_deactivate_af (struct peer *peer, afi_t afi, safi_t safi) -{ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - zlog_err("%s was called for peer-group %s", __func__, peer->host); - return 1; - } - - /* Nothing to do if we've already deactivated this peer */ - if (! peer->afc[afi][safi]) - return 0; - - /* De-activate the address family configuration. */ - peer->afc[afi][safi] = 0; - - if (peer_af_delete(peer, afi, safi) != 0) - { - zlog_err("couldn't delete af structure for peer %s", peer->host); - return 1; - } - - if (peer->status == Established) - { - if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV)) - { - peer->afc_adv[afi][safi] = 0; - peer->afc_nego[afi][safi] = 0; - - if (peer_active_nego (peer)) - { - bgp_capability_send (peer, afi, safi, - CAPABILITY_CODE_MP, - CAPABILITY_ACTION_UNSET); - bgp_clear_route (peer, afi, safi); - peer->pcount[afi][safi] = 0; - } - else - { - peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - } - else - { - peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - } - - return 0; -} - -int -peer_deactivate (struct peer *peer, afi_t afi, safi_t safi) -{ - int ret = 0; - struct peer_group *group; - struct peer *tmp_peer; - struct listnode *node, *nnode; - - /* Nothing to do if we've already de-activated this peer */ - if (! peer->afc[afi][safi]) - return ret; - - /* This is a peer-group so de-activate all of the members of the - * peer-group as well */ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer->afc[afi][safi] = 0; - group = peer->group; - - if (peer_af_delete(peer, afi, safi) != 0) - { - zlog_err("couldn't delete af structure for peer %s", peer->host); - } - - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer)) - { - ret |= non_peergroup_deactivate_af (tmp_peer, afi, safi); - } - } - else - { - ret |= non_peergroup_deactivate_af (peer, afi, safi); - } - - return ret; -} - -int -peer_afc_set (struct peer *peer, afi_t afi, safi_t safi, int enable) -{ - if (enable) - return peer_activate (peer, afi, safi); - else - return peer_deactivate (peer, afi, safi); -} - -static void -peer_nsf_stop (struct peer *peer) -{ - afi_t afi; - safi_t safi; - - UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT); - UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE); - - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_4 ; safi++) - peer->nsf[afi][safi] = 0; - - if (peer->t_gr_restart) - { - BGP_TIMER_OFF (peer->t_gr_restart); - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s graceful restart timer stopped", peer->host); - } - if (peer->t_gr_stale) - { - BGP_TIMER_OFF (peer->t_gr_stale); - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s graceful restart stalepath timer stopped", peer->host); - } - bgp_clear_route_all (peer); +int peer_activate(struct peer *peer, afi_t afi, safi_t safi) +{ + int ret = 0; + struct peer_group *group; + struct listnode *node, *nnode; + struct peer *tmp_peer; + + /* Nothing to do if we've already activated this peer */ + if (peer->afc[afi][safi]) + return ret; + + /* This is a peer-group so activate all of the members of the + * peer-group as well */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + + /* Do not activate a peer for both SAFI_UNICAST and + * SAFI_LABELED_UNICAST */ + if ((safi == SAFI_UNICAST + && peer->afc[afi][SAFI_LABELED_UNICAST]) + || (safi == SAFI_LABELED_UNICAST + && peer->afc[afi][SAFI_UNICAST])) + return BGP_ERR_PEER_SAFI_CONFLICT; + + peer->afc[afi][safi] = 1; + group = peer->group; + + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) { + ret |= non_peergroup_activate_af(tmp_peer, afi, safi); + } + } else { + ret |= non_peergroup_activate_af(peer, afi, safi); + } + + return ret; +} + +static int non_peergroup_deactivate_af(struct peer *peer, afi_t afi, + safi_t safi) +{ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + zlog_err("%s was called for peer-group %s", __func__, + peer->host); + return 1; + } + + /* Nothing to do if we've already deactivated this peer */ + if (!peer->afc[afi][safi]) + return 0; + + /* De-activate the address family configuration. */ + peer->afc[afi][safi] = 0; + + if (peer_af_delete(peer, afi, safi) != 0) { + zlog_err("couldn't delete af structure for peer %s", + peer->host); + return 1; + } + + if (peer->status == Established) { + if (CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV)) { + peer->afc_adv[afi][safi] = 0; + peer->afc_nego[afi][safi] = 0; + + if (peer_active_nego(peer)) { + bgp_capability_send(peer, afi, safi, + CAPABILITY_CODE_MP, + CAPABILITY_ACTION_UNSET); + bgp_clear_route(peer, afi, safi); + peer->pcount[afi][safi] = 0; + } else { + peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } + } else { + peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } + } + + return 0; +} + +int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi) +{ + int ret = 0; + struct peer_group *group; + struct peer *tmp_peer; + struct listnode *node, *nnode; + + /* Nothing to do if we've already de-activated this peer */ + if (!peer->afc[afi][safi]) + return ret; + + /* This is a peer-group so de-activate all of the members of the + * peer-group as well */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer->afc[afi][safi] = 0; + group = peer->group; + + if (peer_af_delete(peer, afi, safi) != 0) { + zlog_err("couldn't delete af structure for peer %s", + peer->host); + } + + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) { + ret |= non_peergroup_deactivate_af(tmp_peer, afi, safi); + } + } else { + ret |= non_peergroup_deactivate_af(peer, afi, safi); + } + + return ret; +} + +int peer_afc_set(struct peer *peer, afi_t afi, safi_t safi, int enable) +{ + if (enable) + return peer_activate(peer, afi, safi); + else + return peer_deactivate(peer, afi, safi); +} + +static void peer_nsf_stop(struct peer *peer) +{ + afi_t afi; + safi_t safi; + + UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT); + UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_RESERVED_4; safi++) + peer->nsf[afi][safi] = 0; + + if (peer->t_gr_restart) { + BGP_TIMER_OFF(peer->t_gr_restart); + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s graceful restart timer stopped", + peer->host); + } + if (peer->t_gr_stale) { + BGP_TIMER_OFF(peer->t_gr_stale); + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s graceful restart stalepath timer stopped", + peer->host); + } + bgp_clear_route_all(peer); } /* Delete peer from confguration. @@ -2002,2679 +1872,2509 @@ peer_nsf_stop (struct peer *peer) * said, getting here for a "Deleted" peer is a bug in the neighbour * FSM. */ -int -peer_delete (struct peer *peer) -{ - int i; - afi_t afi; - safi_t safi; - struct bgp *bgp; - struct bgp_filter *filter; - struct listnode *pn; - int accept_peer; - - assert (peer->status != Deleted); - - bgp = peer->bgp; - accept_peer = CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER); - - if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT)) - peer_nsf_stop (peer); - - SET_FLAG(peer->flags, PEER_FLAG_DELETE); - - /* If this peer belongs to peer group, clear up the - relationship. */ - if (peer->group) - { - if (peer_dynamic_neighbor(peer)) - peer_drop_dynamic_neighbor(peer); - - if ((pn = listnode_lookup (peer->group->peer, peer))) - { - peer = peer_unlock (peer); /* group->peer list reference */ - list_delete_node (peer->group->peer, pn); - } - peer->group = NULL; - } - - /* Withdraw all information from routing table. We can not use - * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is - * executed after peer structure is deleted. - */ - peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE; - bgp_stop (peer); - UNSET_FLAG(peer->flags, PEER_FLAG_DELETE); - - if (peer->doppelganger) - { - peer->doppelganger->doppelganger = NULL; - peer->doppelganger = NULL; - } - - UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER); - bgp_fsm_change_status (peer, Deleted); - - /* Remove from NHT */ - if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) - bgp_unlink_nexthop_by_peer (peer); - - /* Password configuration */ - if (peer->password) - { - XFREE (MTYPE_PEER_PASSWORD, peer->password); - peer->password = NULL; - - if (!accept_peer && - ! BGP_PEER_SU_UNSPEC(peer) && - ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - bgp_md5_unset (peer); - } - - bgp_timer_set (peer); /* stops all timers for Deleted */ - - /* Delete from all peer list. */ - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP) - && (pn = listnode_lookup (bgp->peer, peer))) - { - peer_unlock (peer); /* bgp peer list reference */ - list_delete_node (bgp->peer, pn); - hash_release(bgp->peerhash, peer); - } - - /* Buffers. */ - if (peer->ibuf) - { - stream_free (peer->ibuf); - peer->ibuf = NULL; - } - - if (peer->obuf) - { - stream_fifo_free (peer->obuf); - peer->obuf = NULL; - } - - if (peer->work) - { - stream_free (peer->work); - peer->work = NULL; - } - - if (peer->scratch) - { - stream_free(peer->scratch); - peer->scratch = NULL; - } - - /* Local and remote addresses. */ - if (peer->su_local) - { - sockunion_free (peer->su_local); - peer->su_local = NULL; - } - - if (peer->su_remote) - { - sockunion_free (peer->su_remote); - peer->su_remote = NULL; - } - - /* Free filter related memory. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - filter = &peer->filter[afi][safi]; +int peer_delete(struct peer *peer) +{ + int i; + afi_t afi; + safi_t safi; + struct bgp *bgp; + struct bgp_filter *filter; + struct listnode *pn; + int accept_peer; - for (i = FILTER_IN; i < FILTER_MAX; i++) - { - if (filter->dlist[i].name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[i].name); - filter->dlist[i].name = NULL; - } - - if (filter->plist[i].name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[i].name); - filter->plist[i].name = NULL; - } - - if (filter->aslist[i].name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[i].name); - filter->aslist[i].name = NULL; - } - } - - for (i = RMAP_IN; i < RMAP_MAX; i++) - { - if (filter->map[i].name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->map[i].name); - filter->map[i].name = NULL; - } - } + assert(peer->status != Deleted); - if (filter->usmap.name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); - filter->usmap.name = NULL; - } + bgp = peer->bgp; + accept_peer = CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER); - if (peer->default_rmap[afi][safi].name) - { - XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name); - peer->default_rmap[afi][safi].name = NULL; - } - } + if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) + peer_nsf_stop(peer); + + SET_FLAG(peer->flags, PEER_FLAG_DELETE); + + /* If this peer belongs to peer group, clear up the + relationship. */ + if (peer->group) { + if (peer_dynamic_neighbor(peer)) + peer_drop_dynamic_neighbor(peer); + + if ((pn = listnode_lookup(peer->group->peer, peer))) { + peer = peer_unlock( + peer); /* group->peer list reference */ + list_delete_node(peer->group->peer, pn); + } + peer->group = NULL; + } - FOREACH_AFI_SAFI (afi, safi) - peer_af_delete (peer, afi, safi); + /* Withdraw all information from routing table. We can not use + * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is + * executed after peer structure is deleted. + */ + peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE; + bgp_stop(peer); + UNSET_FLAG(peer->flags, PEER_FLAG_DELETE); + + if (peer->doppelganger) { + peer->doppelganger->doppelganger = NULL; + peer->doppelganger = NULL; + } + + UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER); + bgp_fsm_change_status(peer, Deleted); + + /* Remove from NHT */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + bgp_unlink_nexthop_by_peer(peer); + + /* Password configuration */ + if (peer->password) { + XFREE(MTYPE_PEER_PASSWORD, peer->password); + peer->password = NULL; + + if (!accept_peer && !BGP_PEER_SU_UNSPEC(peer) + && !CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + bgp_md5_unset(peer); + } + + bgp_timer_set(peer); /* stops all timers for Deleted */ + + /* Delete from all peer list. */ + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) + && (pn = listnode_lookup(bgp->peer, peer))) { + peer_unlock(peer); /* bgp peer list reference */ + list_delete_node(bgp->peer, pn); + hash_release(bgp->peerhash, peer); + } + + /* Buffers. */ + if (peer->ibuf) { + stream_free(peer->ibuf); + peer->ibuf = NULL; + } + + if (peer->obuf) { + stream_fifo_free(peer->obuf); + peer->obuf = NULL; + } + + if (peer->work) { + stream_free(peer->work); + peer->work = NULL; + } + + if (peer->scratch) { + stream_free(peer->scratch); + peer->scratch = NULL; + } - if (peer->hostname) - { - XFREE(MTYPE_BGP_PEER_HOST, peer->hostname); - peer->hostname = NULL; - } + /* Local and remote addresses. */ + if (peer->su_local) { + sockunion_free(peer->su_local); + peer->su_local = NULL; + } + + if (peer->su_remote) { + sockunion_free(peer->su_remote); + peer->su_remote = NULL; + } + + /* Free filter related memory. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + filter = &peer->filter[afi][safi]; + + for (i = FILTER_IN; i < FILTER_MAX; i++) { + if (filter->dlist[i].name) { + XFREE(MTYPE_BGP_FILTER_NAME, + filter->dlist[i].name); + filter->dlist[i].name = NULL; + } + + if (filter->plist[i].name) { + XFREE(MTYPE_BGP_FILTER_NAME, + filter->plist[i].name); + filter->plist[i].name = NULL; + } + + if (filter->aslist[i].name) { + XFREE(MTYPE_BGP_FILTER_NAME, + filter->aslist[i].name); + filter->aslist[i].name = NULL; + } + } + + for (i = RMAP_IN; i < RMAP_MAX; i++) { + if (filter->map[i].name) { + XFREE(MTYPE_BGP_FILTER_NAME, + filter->map[i].name); + filter->map[i].name = NULL; + } + } + + if (filter->usmap.name) { + XFREE(MTYPE_BGP_FILTER_NAME, + filter->usmap.name); + filter->usmap.name = NULL; + } + + if (peer->default_rmap[afi][safi].name) { + XFREE(MTYPE_ROUTE_MAP_NAME, + peer->default_rmap[afi][safi].name); + peer->default_rmap[afi][safi].name = NULL; + } + } - if (peer->domainname) - { - XFREE(MTYPE_BGP_PEER_HOST, peer->domainname); - peer->domainname = NULL; - } - - peer_unlock (peer); /* initial reference */ + FOREACH_AFI_SAFI(afi, safi) + peer_af_delete(peer, afi, safi); + + if (peer->hostname) { + XFREE(MTYPE_BGP_PEER_HOST, peer->hostname); + peer->hostname = NULL; + } + + if (peer->domainname) { + XFREE(MTYPE_BGP_PEER_HOST, peer->domainname); + peer->domainname = NULL; + } - return 0; + peer_unlock(peer); /* initial reference */ + + return 0; } -static int -peer_group_cmp (struct peer_group *g1, struct peer_group *g2) +static int peer_group_cmp(struct peer_group *g1, struct peer_group *g2) { - return strcmp (g1->name, g2->name); + return strcmp(g1->name, g2->name); } /* Peer group cofiguration. */ -static struct peer_group * -peer_group_new (void) +static struct peer_group *peer_group_new(void) { - return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP, - sizeof (struct peer_group)); + return (struct peer_group *)XCALLOC(MTYPE_PEER_GROUP, + sizeof(struct peer_group)); } -static void -peer_group_free (struct peer_group *group) +static void peer_group_free(struct peer_group *group) { - XFREE (MTYPE_PEER_GROUP, group); + XFREE(MTYPE_PEER_GROUP, group); } -struct peer_group * -peer_group_lookup (struct bgp *bgp, const char *name) +struct peer_group *peer_group_lookup(struct bgp *bgp, const char *name) { - struct peer_group *group; - struct listnode *node, *nnode; + struct peer_group *group; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) { + if (strcmp(group->name, name) == 0) + return group; + } + return NULL; +} + +struct peer_group *peer_group_get(struct bgp *bgp, const char *name) +{ + struct peer_group *group; + afi_t afi; + + group = peer_group_lookup(bgp, name); + if (group) + return group; + + group = peer_group_new(); + group->bgp = bgp; + if (group->name) + XFREE(MTYPE_PEER_GROUP_HOST, group->name); + group->name = XSTRDUP(MTYPE_PEER_GROUP_HOST, name); + group->peer = list_new(); + for (afi = AFI_IP; afi < AFI_MAX; afi++) + group->listen_range[afi] = list_new(); + group->conf = peer_new(bgp); + if (!bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4)) + group->conf->afc[AFI_IP][SAFI_UNICAST] = 1; + if (group->conf->host) + XFREE(MTYPE_BGP_PEER_HOST, group->conf->host); + group->conf->host = XSTRDUP(MTYPE_BGP_PEER_HOST, name); + group->conf->group = group; + group->conf->as = 0; + group->conf->ttl = 1; + group->conf->gtsm_hops = 0; + group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; + UNSET_FLAG(group->conf->config, PEER_CONFIG_TIMER); + UNSET_FLAG(group->conf->config, PEER_CONFIG_CONNECT); + group->conf->keepalive = 0; + group->conf->holdtime = 0; + group->conf->connect = 0; + SET_FLAG(group->conf->sflags, PEER_STATUS_GROUP); + listnode_add_sort(bgp->group, group); - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - { - if (strcmp (group->name, name) == 0) return group; - } - return NULL; } -struct peer_group * -peer_group_get (struct bgp *bgp, const char *name) -{ - struct peer_group *group; - afi_t afi; - - group = peer_group_lookup (bgp, name); - if (group) - return group; - - group = peer_group_new (); - group->bgp = bgp; - if (group->name) - XFREE(MTYPE_PEER_GROUP_HOST, group->name); - group->name = XSTRDUP(MTYPE_PEER_GROUP_HOST, name); - group->peer = list_new (); - for (afi = AFI_IP; afi < AFI_MAX; afi++) - group->listen_range[afi] = list_new (); - group->conf = peer_new (bgp); - if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)) - group->conf->afc[AFI_IP][SAFI_UNICAST] = 1; - if (group->conf->host) - XFREE(MTYPE_BGP_PEER_HOST, group->conf->host); - group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name); - group->conf->group = group; - group->conf->as = 0; - group->conf->ttl = 1; - group->conf->gtsm_hops = 0; - group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; - UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER); - UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT); - group->conf->keepalive = 0; - group->conf->holdtime = 0; - group->conf->connect = 0; - SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP); - listnode_add_sort (bgp->group, group); - - return group; -} - -static void -peer_group2peer_config_copy (struct peer_group *group, struct peer *peer) -{ - struct peer *conf; - int v6only; - - conf = group->conf; - - /* remote-as */ - if (conf->as) - peer->as = conf->as; - - /* remote-as */ - if (conf->change_local_as) - peer->change_local_as = conf->change_local_as; - - /* TTL */ - peer->ttl = conf->ttl; - - /* GTSM hops */ - peer->gtsm_hops = conf->gtsm_hops; - - /* this flag is per-neighbor and so has to be preserved */ - v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); - - /* peer flags apply */ - peer->flags = conf->flags; - - if (v6only) - SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); - - /* peer config apply */ - peer->config = conf->config; - - /* peer timers apply */ - peer->holdtime = conf->holdtime; - peer->keepalive = conf->keepalive; - peer->connect = conf->connect; - if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT)) - peer->v_connect = conf->connect; - else - peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; - - /* advertisement-interval reset */ - if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV)) - peer->v_routeadv = conf->routeadv; - else - if (peer_sort (peer) == BGP_PEER_IBGP) - peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; - else - peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; - - /* password apply */ - if (conf->password && !peer->password) - peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password); - - if (! BGP_PEER_SU_UNSPEC(peer)) - bgp_md5_set (peer); - - /* update-source apply */ - if (conf->update_source) - { - if (peer->update_source) - sockunion_free (peer->update_source); - if (peer->update_if) - { - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; - } - peer->update_source = sockunion_dup (conf->update_source); - } - else if (conf->update_if) - { - if (peer->update_if) - XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - if (peer->update_source) - { - sockunion_free (peer->update_source); - peer->update_source = NULL; - } - peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if); - } - - bgp_bfd_peer_group2peer_copy(conf, peer); -} - -static void -peer_group2peer_config_copy_af (struct peer_group *group, struct peer *peer, - afi_t afi, safi_t safi) -{ - int in = FILTER_IN; - int out = FILTER_OUT; - struct peer *conf; - struct bgp_filter *pfilter; - struct bgp_filter *gfilter; - - conf = group->conf; - pfilter = &peer->filter[afi][safi]; - gfilter = &conf->filter[afi][safi]; - - /* peer af_flags apply */ - peer->af_flags[afi][safi] = conf->af_flags[afi][safi]; - - /* maximum-prefix */ - peer->pmax[afi][safi] = conf->pmax[afi][safi]; - peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi]; - peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi]; - - /* allowas-in */ - peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi]; - - /* weight */ - peer->weight[afi][safi] = conf->weight[afi][safi]; - - /* default-originate route-map */ - if (conf->default_rmap[afi][safi].name) - { - if (peer->default_rmap[afi][safi].name) - XFREE(MTYPE_BGP_FILTER_NAME, peer->default_rmap[afi][safi].name); - peer->default_rmap[afi][safi].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, conf->default_rmap[afi][safi].name); - peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map; - } - - /* inbound filter apply */ - if (gfilter->dlist[in].name && ! pfilter->dlist[in].name) - { - if (pfilter->dlist[in].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[in].name); - pfilter->dlist[in].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->dlist[in].name); - pfilter->dlist[in].alist = gfilter->dlist[in].alist; - } - - if (gfilter->plist[in].name && ! pfilter->plist[in].name) - { - if (pfilter->plist[in].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[in].name); - pfilter->plist[in].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->plist[in].name); - pfilter->plist[in].plist = gfilter->plist[in].plist; - } - - if (gfilter->aslist[in].name && ! pfilter->aslist[in].name) - { - if (pfilter->aslist[in].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[in].name); - pfilter->aslist[in].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->aslist[in].name); - pfilter->aslist[in].aslist = gfilter->aslist[in].aslist; - } - - if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name) - { - if (pfilter->map[RMAP_IN].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->map[RMAP_IN].name); - pfilter->map[RMAP_IN].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->map[RMAP_IN].name); - pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map; - } - - /* outbound filter apply */ - if (gfilter->dlist[out].name) - { - if (pfilter->dlist[out].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[out].name); - pfilter->dlist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->dlist[out].name); - pfilter->dlist[out].alist = gfilter->dlist[out].alist; - } - else - { - if (pfilter->dlist[out].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[out].name); - pfilter->dlist[out].name = NULL; - pfilter->dlist[out].alist = NULL; - } - - if (gfilter->plist[out].name) - { - if (pfilter->plist[out].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[out].name); - pfilter->plist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->plist[out].name); - pfilter->plist[out].plist = gfilter->plist[out].plist; - } - else - { - if (pfilter->plist[out].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[out].name); - pfilter->plist[out].name = NULL; - pfilter->plist[out].plist = NULL; - } - - if (gfilter->aslist[out].name) - { - if (pfilter->aslist[out].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[out].name); - pfilter->aslist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->aslist[out].name); - pfilter->aslist[out].aslist = gfilter->aslist[out].aslist; - } - else - { - if (pfilter->aslist[out].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[out].name); - pfilter->aslist[out].name = NULL; - pfilter->aslist[out].aslist = NULL; - } - - if (gfilter->map[RMAP_OUT].name) - { - if (pfilter->map[RMAP_OUT].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->map[RMAP_OUT].name); - pfilter->map[RMAP_OUT].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->map[RMAP_OUT].name); - pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map; - } - else - { - if (pfilter->map[RMAP_OUT].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->map[RMAP_OUT].name); - pfilter->map[RMAP_OUT].name = NULL; - pfilter->map[RMAP_OUT].map = NULL; - } - - if (gfilter->usmap.name) - { - if (pfilter->usmap.name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->usmap.name); - pfilter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->usmap.name); - pfilter->usmap.map = gfilter->usmap.map; - } - else - { - if (pfilter->usmap.name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->usmap.name); - pfilter->usmap.name = NULL; - pfilter->usmap.map = NULL; - } -} +static void peer_group2peer_config_copy(struct peer_group *group, + struct peer *peer) +{ + struct peer *conf; + int v6only; + + conf = group->conf; + + /* remote-as */ + if (conf->as) + peer->as = conf->as; + + /* remote-as */ + if (conf->change_local_as) + peer->change_local_as = conf->change_local_as; + + /* TTL */ + peer->ttl = conf->ttl; + + /* GTSM hops */ + peer->gtsm_hops = conf->gtsm_hops; + + /* this flag is per-neighbor and so has to be preserved */ + v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); + + /* peer flags apply */ + peer->flags = conf->flags; + + if (v6only) + SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); + + /* peer config apply */ + peer->config = conf->config; + + /* peer timers apply */ + peer->holdtime = conf->holdtime; + peer->keepalive = conf->keepalive; + peer->connect = conf->connect; + if (CHECK_FLAG(conf->config, PEER_CONFIG_CONNECT)) + peer->v_connect = conf->connect; + else + peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; + + /* advertisement-interval reset */ + if (CHECK_FLAG(conf->config, PEER_CONFIG_ROUTEADV)) + peer->v_routeadv = conf->routeadv; + else if (peer_sort(peer) == BGP_PEER_IBGP) + peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; + else + peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; + + /* password apply */ + if (conf->password && !peer->password) + peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, conf->password); + + if (!BGP_PEER_SU_UNSPEC(peer)) + bgp_md5_set(peer); + + /* update-source apply */ + if (conf->update_source) { + if (peer->update_source) + sockunion_free(peer->update_source); + if (peer->update_if) { + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; + } + peer->update_source = sockunion_dup(conf->update_source); + } else if (conf->update_if) { + if (peer->update_if) + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + if (peer->update_source) { + sockunion_free(peer->update_source); + peer->update_source = NULL; + } + peer->update_if = + XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, conf->update_if); + } + + bgp_bfd_peer_group2peer_copy(conf, peer); +} + +static void peer_group2peer_config_copy_af(struct peer_group *group, + struct peer *peer, afi_t afi, + safi_t safi) +{ + int in = FILTER_IN; + int out = FILTER_OUT; + struct peer *conf; + struct bgp_filter *pfilter; + struct bgp_filter *gfilter; + + conf = group->conf; + pfilter = &peer->filter[afi][safi]; + gfilter = &conf->filter[afi][safi]; + + /* peer af_flags apply */ + peer->af_flags[afi][safi] = conf->af_flags[afi][safi]; + + /* maximum-prefix */ + peer->pmax[afi][safi] = conf->pmax[afi][safi]; + peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi]; + peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi]; + + /* allowas-in */ + peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi]; + + /* weight */ + peer->weight[afi][safi] = conf->weight[afi][safi]; + + /* default-originate route-map */ + if (conf->default_rmap[afi][safi].name) { + if (peer->default_rmap[afi][safi].name) + XFREE(MTYPE_BGP_FILTER_NAME, + peer->default_rmap[afi][safi].name); + peer->default_rmap[afi][safi].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, + conf->default_rmap[afi][safi].name); + peer->default_rmap[afi][safi].map = + conf->default_rmap[afi][safi].map; + } + + /* inbound filter apply */ + if (gfilter->dlist[in].name && !pfilter->dlist[in].name) { + if (pfilter->dlist[in].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[in].name); + pfilter->dlist[in].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->dlist[in].name); + pfilter->dlist[in].alist = gfilter->dlist[in].alist; + } + + if (gfilter->plist[in].name && !pfilter->plist[in].name) { + if (pfilter->plist[in].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[in].name); + pfilter->plist[in].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->plist[in].name); + pfilter->plist[in].plist = gfilter->plist[in].plist; + } + + if (gfilter->aslist[in].name && !pfilter->aslist[in].name) { + if (pfilter->aslist[in].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[in].name); + pfilter->aslist[in].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, + gfilter->aslist[in].name); + pfilter->aslist[in].aslist = gfilter->aslist[in].aslist; + } + + if (gfilter->map[RMAP_IN].name && !pfilter->map[RMAP_IN].name) { + if (pfilter->map[RMAP_IN].name) + XFREE(MTYPE_BGP_FILTER_NAME, + pfilter->map[RMAP_IN].name); + pfilter->map[RMAP_IN].name = XSTRDUP( + MTYPE_BGP_FILTER_NAME, gfilter->map[RMAP_IN].name); + pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map; + } + + /* outbound filter apply */ + if (gfilter->dlist[out].name) { + if (pfilter->dlist[out].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[out].name); + pfilter->dlist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, + gfilter->dlist[out].name); + pfilter->dlist[out].alist = gfilter->dlist[out].alist; + } else { + if (pfilter->dlist[out].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[out].name); + pfilter->dlist[out].name = NULL; + pfilter->dlist[out].alist = NULL; + } + + if (gfilter->plist[out].name) { + if (pfilter->plist[out].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[out].name); + pfilter->plist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, + gfilter->plist[out].name); + pfilter->plist[out].plist = gfilter->plist[out].plist; + } else { + if (pfilter->plist[out].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[out].name); + pfilter->plist[out].name = NULL; + pfilter->plist[out].plist = NULL; + } + + if (gfilter->aslist[out].name) { + if (pfilter->aslist[out].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[out].name); + pfilter->aslist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, + gfilter->aslist[out].name); + pfilter->aslist[out].aslist = gfilter->aslist[out].aslist; + } else { + if (pfilter->aslist[out].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[out].name); + pfilter->aslist[out].name = NULL; + pfilter->aslist[out].aslist = NULL; + } + + if (gfilter->map[RMAP_OUT].name) { + if (pfilter->map[RMAP_OUT].name) + XFREE(MTYPE_BGP_FILTER_NAME, + pfilter->map[RMAP_OUT].name); + pfilter->map[RMAP_OUT].name = XSTRDUP( + MTYPE_BGP_FILTER_NAME, gfilter->map[RMAP_OUT].name); + pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map; + } else { + if (pfilter->map[RMAP_OUT].name) + XFREE(MTYPE_BGP_FILTER_NAME, + pfilter->map[RMAP_OUT].name); + pfilter->map[RMAP_OUT].name = NULL; + pfilter->map[RMAP_OUT].map = NULL; + } + + if (gfilter->usmap.name) { + if (pfilter->usmap.name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->usmap.name); + pfilter->usmap.name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->usmap.name); + pfilter->usmap.map = gfilter->usmap.map; + } else { + if (pfilter->usmap.name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->usmap.name); + pfilter->usmap.name = NULL; + pfilter->usmap.map = NULL; + } +} /* Peer group's remote AS configuration. */ -int -peer_group_remote_as (struct bgp *bgp, const char *group_name, - as_t *as, int as_type) +int peer_group_remote_as(struct bgp *bgp, const char *group_name, as_t *as, + int as_type) { - struct peer_group *group; - struct peer *peer; - struct listnode *node, *nnode; + struct peer_group *group; + struct peer *peer; + struct listnode *node, *nnode; - group = peer_group_lookup (bgp, group_name); - if (! group) - return -1; + group = peer_group_lookup(bgp, group_name); + if (!group) + return -1; - if ((as_type == group->conf->as_type) && (group->conf->as == *as)) - return 0; + if ((as_type == group->conf->as_type) && (group->conf->as == *as)) + return 0; - /* When we setup peer-group AS number all peer group member's AS - number must be updated to same number. */ - peer_as_change (group->conf, *as, as_type); + /* When we setup peer-group AS number all peer group member's AS + number must be updated to same number. */ + peer_as_change(group->conf, *as, as_type); - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (((peer->as_type == AS_SPECIFIED) && peer->as != *as) || - (peer->as_type != as_type)) - peer_as_change (peer, *as, as_type); - } + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (((peer->as_type == AS_SPECIFIED) && peer->as != *as) + || (peer->as_type != as_type)) + peer_as_change(peer, *as, as_type); + } - return 0; + return 0; } -int -peer_group_delete (struct peer_group *group) +int peer_group_delete(struct peer_group *group) { - struct bgp *bgp; - struct peer *peer; - struct prefix *prefix; - struct peer *other; - struct listnode *node, *nnode; - afi_t afi; + struct bgp *bgp; + struct peer *peer; + struct prefix *prefix; + struct peer *other; + struct listnode *node, *nnode; + afi_t afi; - bgp = group->bgp; + bgp = group->bgp; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - other = peer->doppelganger; - peer_delete (peer); - if (other && other->status != Deleted) - { - other->group = NULL; - peer_delete(other); + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + other = peer->doppelganger; + peer_delete(peer); + if (other && other->status != Deleted) { + other->group = NULL; + peer_delete(other); + } } - } - list_delete (group->peer); + list_delete(group->peer); - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, prefix)) - { - prefix_free(prefix); - } - list_delete (group->listen_range[afi]); - } + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode, + prefix)) { + prefix_free(prefix); + } + list_delete(group->listen_range[afi]); + } - XFREE(MTYPE_PEER_GROUP_HOST, group->name); - group->name = NULL; + XFREE(MTYPE_PEER_GROUP_HOST, group->name); + group->name = NULL; - bfd_info_free(&(group->conf->bfd_info)); + bfd_info_free(&(group->conf->bfd_info)); - group->conf->group = NULL; - peer_delete (group->conf); + group->conf->group = NULL; + peer_delete(group->conf); - /* Delete from all peer_group list. */ - listnode_delete (bgp->group, group); + /* Delete from all peer_group list. */ + listnode_delete(bgp->group, group); - peer_group_free (group); + peer_group_free(group); - return 0; + return 0; } -int -peer_group_remote_as_delete (struct peer_group *group) +int peer_group_remote_as_delete(struct peer_group *group) { - struct peer *peer, *other; - struct listnode *node, *nnode; + struct peer *peer, *other; + struct listnode *node, *nnode; - if ((group->conf->as_type == AS_UNSPECIFIED) || - ((! group->conf->as) && (group->conf->as_type == AS_SPECIFIED))) - return 0; + if ((group->conf->as_type == AS_UNSPECIFIED) + || ((!group->conf->as) && (group->conf->as_type == AS_SPECIFIED))) + return 0; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - other = peer->doppelganger; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + other = peer->doppelganger; - peer_delete (peer); + peer_delete(peer); - if (other && other->status != Deleted) - { - other->group = NULL; - peer_delete(other); + if (other && other->status != Deleted) { + other->group = NULL; + peer_delete(other); + } } - } - list_delete_all_node (group->peer); + list_delete_all_node(group->peer); - group->conf->as = 0; - group->conf->as_type = AS_UNSPECIFIED; + group->conf->as = 0; + group->conf->as_type = AS_UNSPECIFIED; - return 0; + return 0; } -int -peer_group_listen_range_add (struct peer_group *group, struct prefix *range) +int peer_group_listen_range_add(struct peer_group *group, struct prefix *range) { - struct prefix *prefix; - struct listnode *node, *nnode; - afi_t afi; + struct prefix *prefix; + struct listnode *node, *nnode; + afi_t afi; - afi = family2afi(range->family); + afi = family2afi(range->family); - /* Group needs remote AS configured. */ - if (group->conf->as_type == AS_UNSPECIFIED) - return BGP_ERR_PEER_GROUP_NO_REMOTE_AS; + /* Group needs remote AS configured. */ + if (group->conf->as_type == AS_UNSPECIFIED) + return BGP_ERR_PEER_GROUP_NO_REMOTE_AS; - /* Ensure no duplicates. Currently we don't care about overlaps. */ - for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, prefix)) - { - if (prefix_same(range, prefix)) - return 0; - } + /* Ensure no duplicates. Currently we don't care about overlaps. */ + for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode, prefix)) { + if (prefix_same(range, prefix)) + return 0; + } - prefix = prefix_new(); - prefix_copy(prefix, range); - listnode_add(group->listen_range[afi], prefix); - return 0; + prefix = prefix_new(); + prefix_copy(prefix, range); + listnode_add(group->listen_range[afi], prefix); + return 0; } -int -peer_group_listen_range_del (struct peer_group *group, struct prefix *range) +int peer_group_listen_range_del(struct peer_group *group, struct prefix *range) { - struct prefix *prefix, prefix2; - struct listnode *node, *nnode; - struct peer *peer; - afi_t afi; - char buf[PREFIX2STR_BUFFER]; + struct prefix *prefix, prefix2; + struct listnode *node, *nnode; + struct peer *peer; + afi_t afi; + char buf[PREFIX2STR_BUFFER]; - afi = family2afi(range->family); + afi = family2afi(range->family); - /* Identify the listen range. */ - for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, prefix)) - { - if (prefix_same(range, prefix)) - break; - } + /* Identify the listen range. */ + for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode, prefix)) { + if (prefix_same(range, prefix)) + break; + } - if (!prefix) - return BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND; + if (!prefix) + return BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND; + + prefix2str(prefix, buf, sizeof(buf)); + + /* Dispose off any dynamic neighbors that exist due to this listen range + */ + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (!peer_dynamic_neighbor(peer)) + continue; + + sockunion2hostprefix(&peer->su, &prefix2); + if (prefix_match(prefix, &prefix2)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "Deleting dynamic neighbor %s group %s upon " + "delete of listen range %s", + peer->host, group->name, buf); + peer_delete(peer); + } + } - prefix2str(prefix, buf, sizeof(buf)); + /* Get rid of the listen range */ + listnode_delete(group->listen_range[afi], prefix); + + return 0; +} - /* Dispose off any dynamic neighbors that exist due to this listen range */ - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (!peer_dynamic_neighbor (peer)) - continue; +/* Bind specified peer to peer group. */ +int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer, + struct peer_group *group, as_t *as) +{ + int first_member = 0; + afi_t afi; + safi_t safi; + int cap_enhe_preset = 0; + + /* Lookup the peer. */ + if (!peer) + peer = peer_lookup(bgp, su); + + /* The peer exist, bind it to the peer-group */ + if (peer) { + /* When the peer already belongs to peer group, check the + * consistency. */ + if (peer_group_active(peer) + && strcmp(peer->group->name, group->name) != 0) + return BGP_ERR_PEER_GROUP_CANT_CHANGE; + + /* The peer has not specified a remote-as, inherit it from the + * peer-group */ + if (peer->as_type == AS_UNSPECIFIED) { + peer->as_type = group->conf->as_type; + peer->as = group->conf->as; + } - sockunion2hostprefix(&peer->su, &prefix2); - if (prefix_match(prefix, &prefix2)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("Deleting dynamic neighbor %s group %s upon " - "delete of listen range %s", - peer->host, group->name, buf); - peer_delete (peer); - } - } + if (!group->conf->as) { + if (peer_sort(group->conf) != BGP_PEER_INTERNAL + && peer_sort(group->conf) != peer_sort(peer)) { + if (as) + *as = peer->as; + return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT; + } - /* Get rid of the listen range */ - listnode_delete(group->listen_range[afi], prefix); + if (peer_sort(group->conf) == BGP_PEER_INTERNAL) + first_member = 1; + } - return 0; + if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)) + cap_enhe_preset = 1; + + peer_group2peer_config_copy(group, peer); + + /* + * Capability extended-nexthop is enabled for an interface + * neighbor by + * default. So, fix that up here. + */ + if (peer->conf_if && cap_enhe_preset) + peer_flag_set(peer, PEER_FLAG_CAPABILITY_ENHE); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + if (group->conf->afc[afi][safi]) { + peer->afc[afi][safi] = 1; + + if (peer_af_find(peer, afi, safi) + || peer_af_create(peer, afi, + safi)) { + peer_group2peer_config_copy_af( + group, peer, afi, safi); + } + } else if (peer->afc[afi][safi]) + peer_deactivate(peer, afi, safi); + } + + if (peer->group) { + assert(group && peer->group == group); + } else { + struct listnode *pn; + pn = listnode_lookup(bgp->peer, peer); + list_delete_node(bgp->peer, pn); + peer->group = group; + listnode_add_sort(bgp->peer, peer); + + peer = peer_lock(peer); /* group->peer list reference */ + listnode_add(group->peer, peer); + } + + if (first_member) { + /* Advertisement-interval reset */ + if (!CHECK_FLAG(group->conf->config, + PEER_CONFIG_ROUTEADV)) { + if (peer_sort(group->conf) == BGP_PEER_IBGP) + group->conf->v_routeadv = + BGP_DEFAULT_IBGP_ROUTEADV; + else + group->conf->v_routeadv = + BGP_DEFAULT_EBGP_ROUTEADV; + } + + /* ebgp-multihop reset */ + if (peer_sort(group->conf) == BGP_PEER_IBGP) + group->conf->ttl = MAXTTL; + + /* local-as reset */ + if (peer_sort(group->conf) != BGP_PEER_EBGP) { + group->conf->change_local_as = 0; + UNSET_FLAG(peer->flags, + PEER_FLAG_LOCAL_AS_NO_PREPEND); + UNSET_FLAG(peer->flags, + PEER_FLAG_LOCAL_AS_REPLACE_AS); + } + } + + SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_RMAP_BIND; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else { + bgp_session_reset(peer); + } + } + + /* Create a new peer. */ + else { + if ((group->conf->as_type == AS_SPECIFIED) + && (!group->conf->as)) { + return BGP_ERR_PEER_GROUP_NO_REMOTE_AS; + } + + peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as, + group->conf->as_type, 0, 0, group); + + peer = peer_lock(peer); /* group->peer list reference */ + listnode_add(group->peer, peer); + + peer_group2peer_config_copy(group, peer); + + /* If the peer-group is active for this afi/safi then activate + * for this peer */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + if (group->conf->afc[afi][safi]) { + peer->afc[afi][safi] = 1; + peer_af_create(peer, afi, safi); + peer_group2peer_config_copy_af( + group, peer, afi, safi); + } else if (peer->afc[afi][safi]) + peer_deactivate(peer, afi, safi); + + SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); + + /* Set up peer's events and timers. */ + if (peer_active(peer)) + bgp_timer_set(peer); + } + + return 0; } -/* Bind specified peer to peer group. */ -int -peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer, - struct peer_group *group, as_t *as) -{ - int first_member = 0; - afi_t afi; - safi_t safi; - int cap_enhe_preset = 0; - - /* Lookup the peer. */ - if (!peer) - peer = peer_lookup (bgp, su); - - /* The peer exist, bind it to the peer-group */ - if (peer) - { - /* When the peer already belongs to peer group, check the consistency. */ - if (peer_group_active (peer) && strcmp (peer->group->name, group->name) != 0) - return BGP_ERR_PEER_GROUP_CANT_CHANGE; - - /* The peer has not specified a remote-as, inherit it from the - * peer-group */ - if (peer->as_type == AS_UNSPECIFIED) - { - peer->as_type = group->conf->as_type; - peer->as = group->conf->as; - } - - if (! group->conf->as) - { - if (peer_sort (group->conf) != BGP_PEER_INTERNAL - && peer_sort (group->conf) != peer_sort (peer)) - { - if (as) - *as = peer->as; - return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT; - } - - if (peer_sort (group->conf) == BGP_PEER_INTERNAL) - first_member = 1; - } - - if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE)) - cap_enhe_preset = 1; - - peer_group2peer_config_copy(group, peer); - - /* - * Capability extended-nexthop is enabled for an interface neighbor by - * default. So, fix that up here. - */ - if (peer->conf_if && cap_enhe_preset) - peer_flag_set (peer, PEER_FLAG_CAPABILITY_ENHE); - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - if (group->conf->afc[afi][safi]) - { - peer->afc[afi][safi] = 1; - - if (peer_af_find(peer, afi, safi) || peer_af_create(peer, afi, safi)) - { - peer_group2peer_config_copy_af (group, peer, afi, safi); - } - } - else if (peer->afc[afi][safi]) - peer_deactivate (peer, afi, safi); - } - - if (peer->group) - { - assert (group && peer->group == group); - } - else - { - struct listnode *pn; - pn = listnode_lookup (bgp->peer, peer); - list_delete_node (bgp->peer, pn); - peer->group = group; - listnode_add_sort (bgp->peer, peer); - - peer = peer_lock (peer); /* group->peer list reference */ - listnode_add (group->peer, peer); - } - - if (first_member) - { - /* Advertisement-interval reset */ - if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV)) - { - if (peer_sort (group->conf) == BGP_PEER_IBGP) - group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; - else - group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; - } - - /* ebgp-multihop reset */ - if (peer_sort (group->conf) == BGP_PEER_IBGP) - group->conf->ttl = MAXTTL; - - /* local-as reset */ - if (peer_sort (group->conf) != BGP_PEER_EBGP) - { - group->conf->change_local_as = 0; - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); - } - } - - SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_RMAP_BIND; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - { - bgp_session_reset(peer); - } - } - - /* Create a new peer. */ - else - { - if ((group->conf->as_type == AS_SPECIFIED) && (! group->conf->as)) - { - return BGP_ERR_PEER_GROUP_NO_REMOTE_AS; - } - - peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, group->conf->as_type, 0, 0, group); - - peer = peer_lock (peer); /* group->peer list reference */ - listnode_add (group->peer, peer); - - peer_group2peer_config_copy(group, peer); - - /* If the peer-group is active for this afi/safi then activate for this peer */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - if (group->conf->afc[afi][safi]) - { - peer->afc[afi][safi] = 1; - peer_af_create(peer, afi, safi); - peer_group2peer_config_copy_af (group, peer, afi, safi); - } - else if (peer->afc[afi][safi]) - peer_deactivate (peer, afi, safi); - - SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); - - /* Set up peer's events and timers. */ - if (peer_active (peer)) - bgp_timer_set (peer); - } - - return 0; -} - -int -peer_group_unbind (struct bgp *bgp, struct peer *peer, - struct peer_group *group) -{ - struct peer *other; - afi_t afi; - safi_t safi; - - if (group != peer->group) - return BGP_ERR_PEER_GROUP_MISMATCH; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - if (peer->afc[afi][safi]) - { - peer->afc[afi][safi] = 0; - peer_af_flag_reset (peer, afi, safi); - - if (peer_af_delete(peer, afi, safi) != 0) - { - zlog_err("couldn't delete af structure for peer %s", peer->host); - } - } - } - - assert (listnode_lookup (group->peer, peer)); - peer_unlock (peer); /* peer group list reference */ - listnode_delete (group->peer, peer); - peer->group = NULL; - other = peer->doppelganger; - - if (group->conf->as) - { - peer_delete (peer); - if (other && other->status != Deleted) - { - if (other->group) - { - peer_unlock(other); - listnode_delete(group->peer, other); - } - other->group = NULL; - peer_delete(other); - } - return 0; - } - - bgp_bfd_deregister_peer(peer); - peer_global_config_reset (peer); - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_RMAP_UNBIND; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - - return 0; -} - -static int -bgp_startup_timer_expire (struct thread *thread) -{ - struct bgp *bgp; - - bgp = THREAD_ARG (thread); - bgp->t_startup = NULL; - - return 0; +int peer_group_unbind(struct bgp *bgp, struct peer *peer, + struct peer_group *group) +{ + struct peer *other; + afi_t afi; + safi_t safi; + + if (group != peer->group) + return BGP_ERR_PEER_GROUP_MISMATCH; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + if (peer->afc[afi][safi]) { + peer->afc[afi][safi] = 0; + peer_af_flag_reset(peer, afi, safi); + + if (peer_af_delete(peer, afi, safi) != 0) { + zlog_err( + "couldn't delete af structure for peer %s", + peer->host); + } + } + } + + assert(listnode_lookup(group->peer, peer)); + peer_unlock(peer); /* peer group list reference */ + listnode_delete(group->peer, peer); + peer->group = NULL; + other = peer->doppelganger; + + if (group->conf->as) { + peer_delete(peer); + if (other && other->status != Deleted) { + if (other->group) { + peer_unlock(other); + listnode_delete(group->peer, other); + } + other->group = NULL; + peer_delete(other); + } + return 0; + } + + bgp_bfd_deregister_peer(peer); + peer_global_config_reset(peer); + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_RMAP_UNBIND; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + + return 0; +} + +static int bgp_startup_timer_expire(struct thread *thread) +{ + struct bgp *bgp; + + bgp = THREAD_ARG(thread); + bgp->t_startup = NULL; + + return 0; } /* BGP instance creation by `router bgp' commands. */ -static struct bgp * -bgp_create (as_t *as, const char *name, enum bgp_instance_type inst_type) -{ - struct bgp *bgp; - afi_t afi; - safi_t safi; - - if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL) - return NULL; - - if (BGP_DEBUG (zebra, ZEBRA)) - { - if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) - zlog_debug("Creating Default VRF, AS %u", *as); - else - zlog_debug("Creating %s %s, AS %u", - (inst_type == BGP_INSTANCE_TYPE_VRF) ? "VRF" : "VIEW", - name, *as); - } - - bgp_lock (bgp); - bgp->inst_type = inst_type; - bgp->vrf_id = (inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? - VRF_DEFAULT : VRF_UNKNOWN; - bgp->peer_self = peer_new (bgp); - if (bgp->peer_self->host) - XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host); - bgp->peer_self->host = XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement"); - bgp->peer = list_new (); - bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp; - bgp->peerhash = hash_create (peer_hash_key_make, peer_hash_cmp, NULL); - - bgp->group = list_new (); - bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - bgp->route[afi][safi] = bgp_table_init (afi, safi); - bgp->aggregate[afi][safi] = bgp_table_init (afi, safi); - bgp->rib[afi][safi] = bgp_table_init (afi, safi); - - /* Enable maximum-paths */ - bgp_maximum_paths_set (bgp, afi, safi, BGP_PEER_EBGP, multipath_num, 0); - bgp_maximum_paths_set (bgp, afi, safi, BGP_PEER_IBGP, multipath_num, 0); - } - - bgp->v_update_delay = BGP_UPDATE_DELAY_DEF; - bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF; - bgp->default_subgroup_pkt_queue_max = BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX; - bgp->default_holdtime = BGP_DEFAULT_HOLDTIME; - bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE; - bgp->restart_time = BGP_DEFAULT_RESTART_TIME; - bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME; - bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT; - bgp->dynamic_neighbors_count = 0; +static struct bgp *bgp_create(as_t *as, const char *name, + enum bgp_instance_type inst_type) +{ + struct bgp *bgp; + afi_t afi; + safi_t safi; + + if ((bgp = XCALLOC(MTYPE_BGP, sizeof(struct bgp))) == NULL) + return NULL; + + if (BGP_DEBUG(zebra, ZEBRA)) { + if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) + zlog_debug("Creating Default VRF, AS %u", *as); + else + zlog_debug("Creating %s %s, AS %u", + (inst_type == BGP_INSTANCE_TYPE_VRF) + ? "VRF" + : "VIEW", + name, *as); + } + + bgp_lock(bgp); + bgp->inst_type = inst_type; + bgp->vrf_id = (inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? VRF_DEFAULT + : VRF_UNKNOWN; + bgp->peer_self = peer_new(bgp); + if (bgp->peer_self->host) + XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host); + bgp->peer_self->host = + XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement"); + bgp->peer = list_new(); + bgp->peer->cmp = (int (*)(void *, void *))peer_cmp; + bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_cmp, NULL); + + bgp->group = list_new(); + bgp->group->cmp = (int (*)(void *, void *))peer_group_cmp; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + bgp->route[afi][safi] = bgp_table_init(afi, safi); + bgp->aggregate[afi][safi] = bgp_table_init(afi, safi); + bgp->rib[afi][safi] = bgp_table_init(afi, safi); + + /* Enable maximum-paths */ + bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_EBGP, + multipath_num, 0); + bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_IBGP, + multipath_num, 0); + } + + bgp->v_update_delay = BGP_UPDATE_DELAY_DEF; + bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF; + bgp->default_subgroup_pkt_queue_max = + BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX; + bgp->default_holdtime = BGP_DEFAULT_HOLDTIME; + bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE; + bgp->restart_time = BGP_DEFAULT_RESTART_TIME; + bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME; + bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT; + bgp->dynamic_neighbors_count = 0; #if DFLT_BGP_IMPORT_CHECK - bgp_flag_set (bgp, BGP_FLAG_IMPORT_CHECK); + bgp_flag_set(bgp, BGP_FLAG_IMPORT_CHECK); #endif #if DFLT_BGP_SHOW_HOSTNAME - bgp_flag_set (bgp, BGP_FLAG_SHOW_HOSTNAME); + bgp_flag_set(bgp, BGP_FLAG_SHOW_HOSTNAME); #endif #if DFLT_BGP_LOG_NEIGHBOR_CHANGES - bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES); + bgp_flag_set(bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES); #endif #if DFLT_BGP_DETERMINISTIC_MED - bgp_flag_set (bgp, BGP_FLAG_DETERMINISTIC_MED); + bgp_flag_set(bgp, BGP_FLAG_DETERMINISTIC_MED); #endif - bgp->addpath_tx_id = BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE; + bgp->addpath_tx_id = BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE; - bgp->as = *as; + bgp->as = *as; #if ENABLE_BGP_VNC - if (inst_type != BGP_INSTANCE_TYPE_VRF) - { - bgp->rfapi = bgp_rfapi_new(bgp); - assert(bgp->rfapi); - assert(bgp->rfapi_cfg); - } + if (inst_type != BGP_INSTANCE_TYPE_VRF) { + bgp->rfapi = bgp_rfapi_new(bgp); + assert(bgp->rfapi); + assert(bgp->rfapi_cfg); + } #endif /* ENABLE_BGP_VNC */ - if (name) - { - bgp->name = XSTRDUP(MTYPE_BGP, name); - } - else - { - /* TODO - The startup timer needs to be run for the whole of BGP */ - thread_add_timer(bm->master, bgp_startup_timer_expire, bgp, - bgp->restart_time, &bgp->t_startup); - } + if (name) { + bgp->name = XSTRDUP(MTYPE_BGP, name); + } else { + /* TODO - The startup timer needs to be run for the whole of BGP + */ + thread_add_timer(bm->master, bgp_startup_timer_expire, bgp, + bgp->restart_time, &bgp->t_startup); + } - bgp->wpkt_quanta = BGP_WRITE_PACKET_MAX; - bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME; + bgp->wpkt_quanta = BGP_WRITE_PACKET_MAX; + bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME; - QOBJ_REG (bgp, bgp); + QOBJ_REG(bgp, bgp); - update_bgp_group_init(bgp); - bgp_evpn_init(bgp); - return bgp; + update_bgp_group_init(bgp); + bgp_evpn_init(bgp); + return bgp; } /* Return the "default VRF" instance of BGP. */ -struct bgp * -bgp_get_default (void) +struct bgp *bgp_get_default(void) { - struct bgp *bgp; - struct listnode *node, *nnode; + struct bgp *bgp; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - return bgp; - return NULL; + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) + if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + return bgp; + return NULL; } /* Lookup BGP entry. */ -struct bgp * -bgp_lookup (as_t as, const char *name) +struct bgp *bgp_lookup(as_t as, const char *name) { - struct bgp *bgp; - struct listnode *node, *nnode; + struct bgp *bgp; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - if (bgp->as == as - && ((bgp->name == NULL && name == NULL) - || (bgp->name && name && strcmp (bgp->name, name) == 0))) - return bgp; - return NULL; + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) + if (bgp->as == as + && ((bgp->name == NULL && name == NULL) + || (bgp->name && name && strcmp(bgp->name, name) == 0))) + return bgp; + return NULL; } /* Lookup BGP structure by view name. */ -struct bgp * -bgp_lookup_by_name (const char *name) +struct bgp *bgp_lookup_by_name(const char *name) { - struct bgp *bgp; - struct listnode *node, *nnode; + struct bgp *bgp; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - if ((bgp->name == NULL && name == NULL) - || (bgp->name && name && strcmp (bgp->name, name) == 0)) - return bgp; - return NULL; + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) + if ((bgp->name == NULL && name == NULL) + || (bgp->name && name && strcmp(bgp->name, name) == 0)) + return bgp; + return NULL; } /* Lookup BGP instance based on VRF id. */ /* Note: Only to be used for incoming messages from Zebra. */ -struct bgp * -bgp_lookup_by_vrf_id (vrf_id_t vrf_id) +struct bgp *bgp_lookup_by_vrf_id(vrf_id_t vrf_id) { - struct vrf *vrf; + struct vrf *vrf; - /* Lookup VRF (in tree) and follow link. */ - vrf = vrf_lookup_by_id (vrf_id); - if (!vrf) - return NULL; - return (vrf->info) ? (struct bgp *)vrf->info : NULL; + /* Lookup VRF (in tree) and follow link. */ + vrf = vrf_lookup_by_id(vrf_id); + if (!vrf) + return NULL; + return (vrf->info) ? (struct bgp *)vrf->info : NULL; } /* Called from VTY commands. */ -int -bgp_get (struct bgp **bgp_val, as_t *as, const char *name, - enum bgp_instance_type inst_type) -{ - struct bgp *bgp; - - /* Multiple instance check. */ - if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE)) - { - if (name) - bgp = bgp_lookup_by_name (name); - else - bgp = bgp_get_default (); - - /* Already exists. */ - if (bgp) - { - if (bgp->as != *as) - { - *as = bgp->as; - return BGP_ERR_INSTANCE_MISMATCH; - } - if (bgp->inst_type != inst_type) - return BGP_ERR_INSTANCE_MISMATCH; - *bgp_val = bgp; - return 0; - } - } - else - { - /* BGP instance name can not be specified for single instance. */ - if (name) - return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET; - - /* Get default BGP structure if exists. */ - bgp = bgp_get_default (); - - if (bgp) - { - if (bgp->as != *as) - { - *as = bgp->as; - return BGP_ERR_AS_MISMATCH; - } - *bgp_val = bgp; - return 0; +int bgp_get(struct bgp **bgp_val, as_t *as, const char *name, + enum bgp_instance_type inst_type) +{ + struct bgp *bgp; + + /* Multiple instance check. */ + if (bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) { + if (name) + bgp = bgp_lookup_by_name(name); + else + bgp = bgp_get_default(); + + /* Already exists. */ + if (bgp) { + if (bgp->as != *as) { + *as = bgp->as; + return BGP_ERR_INSTANCE_MISMATCH; + } + if (bgp->inst_type != inst_type) + return BGP_ERR_INSTANCE_MISMATCH; + *bgp_val = bgp; + return 0; + } + } else { + /* BGP instance name can not be specified for single instance. + */ + if (name) + return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET; + + /* Get default BGP structure if exists. */ + bgp = bgp_get_default(); + + if (bgp) { + if (bgp->as != *as) { + *as = bgp->as; + return BGP_ERR_AS_MISMATCH; + } + *bgp_val = bgp; + return 0; + } } - } - bgp = bgp_create (as, name, inst_type); - bgp_router_id_set(bgp, &bgp->router_id_zebra); - bgp_address_init (bgp); - bgp_scan_init (bgp); - *bgp_val = bgp; + bgp = bgp_create(as, name, inst_type); + bgp_router_id_set(bgp, &bgp->router_id_zebra); + bgp_address_init(bgp); + bgp_scan_init(bgp); + *bgp_val = bgp; - bgp->t_rmap_def_originate_eval = NULL; + bgp->t_rmap_def_originate_eval = NULL; - /* Create BGP server socket, if first instance. */ - if (list_isempty(bm->bgp) - && !bgp_option_check (BGP_OPT_NO_LISTEN)) - { - if (bgp_socket (bm->port, bm->address) < 0) - return BGP_ERR_INVALID_VALUE; - } + /* Create BGP server socket, if first instance. */ + if (list_isempty(bm->bgp) && !bgp_option_check(BGP_OPT_NO_LISTEN)) { + if (bgp_socket(bm->port, bm->address) < 0) + return BGP_ERR_INVALID_VALUE; + } - listnode_add (bm->bgp, bgp); + listnode_add(bm->bgp, bgp); - /* If Default instance or VRF, link to the VRF structure, if present. */ - if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT || - bgp->inst_type == BGP_INSTANCE_TYPE_VRF) - { - struct vrf *vrf; + /* If Default instance or VRF, link to the VRF structure, if present. */ + if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT + || bgp->inst_type == BGP_INSTANCE_TYPE_VRF) { + struct vrf *vrf; - vrf = bgp_vrf_lookup_by_instance_type (bgp); - if (vrf) - bgp_vrf_link (bgp, vrf); - } + vrf = bgp_vrf_lookup_by_instance_type(bgp); + if (vrf) + bgp_vrf_link(bgp, vrf); + } - /* Register with Zebra, if needed */ - if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) - bgp_zebra_instance_register (bgp); + /* Register with Zebra, if needed */ + if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + bgp_zebra_instance_register(bgp); - return 0; + return 0; } /* * Make BGP instance "up". Applies only to VRFs (non-default) and * implies the VRF has been learnt from Zebra. */ -void -bgp_instance_up (struct bgp *bgp) +void bgp_instance_up(struct bgp *bgp) { - struct peer *peer; - struct listnode *node, *next; + struct peer *peer; + struct listnode *node, *next; - /* Register with zebra. */ - bgp_zebra_instance_register (bgp); + /* Register with zebra. */ + bgp_zebra_instance_register(bgp); - /* Kick off any peers that may have been configured. */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer)) - { - if (!BGP_PEER_START_SUPPRESSED (peer)) - BGP_EVENT_ADD (peer, BGP_Start); - } + /* Kick off any peers that may have been configured. */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) { + if (!BGP_PEER_START_SUPPRESSED(peer)) + BGP_EVENT_ADD(peer, BGP_Start); + } - /* Process any networks that have been configured. */ - bgp_static_add (bgp); + /* Process any networks that have been configured. */ + bgp_static_add(bgp); } /* * Make BGP instance "down". Applies only to VRFs (non-default) and * implies the VRF has been deleted by Zebra. */ -void -bgp_instance_down (struct bgp *bgp) +void bgp_instance_down(struct bgp *bgp) { - struct peer *peer; - struct listnode *node; - struct listnode *next; + struct peer *peer; + struct listnode *node; + struct listnode *next; - /* Stop timers. */ - if (bgp->t_rmap_def_originate_eval) - { - BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval); - bgp_unlock(bgp); /* TODO - This timer is started with a lock - why? */ - } + /* Stop timers. */ + if (bgp->t_rmap_def_originate_eval) { + BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval); + bgp_unlock(bgp); /* TODO - This timer is started with a lock - + why? */ + } - /* Bring down peers, so corresponding routes are purged. */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); - else - bgp_session_reset(peer); - } + /* Bring down peers, so corresponding routes are purged. */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); + else + bgp_session_reset(peer); + } - /* Purge network and redistributed routes. */ - bgp_purge_static_redist_routes (bgp); + /* Purge network and redistributed routes. */ + bgp_purge_static_redist_routes(bgp); } /* Delete BGP instance. */ -int -bgp_delete (struct bgp *bgp) -{ - struct peer *peer; - struct peer_group *group; - struct listnode *node, *next; - struct vrf *vrf; - afi_t afi; - int i; - - THREAD_OFF (bgp->t_startup); - - if (BGP_DEBUG (zebra, ZEBRA)) - { - if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - zlog_debug("Deleting Default VRF"); - else - zlog_debug("Deleting %s %s", - (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) ? "VRF" : "VIEW", - bgp->name); - } - - /* Stop timers. */ - if (bgp->t_rmap_def_originate_eval) - { - BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval); - bgp_unlock(bgp); /* TODO - This timer is started with a lock - why? */ - } - - /* Inform peers we're going down. */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); - } - - /* Delete static routes (networks). */ - bgp_static_delete (bgp); - - /* Unset redistribution. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (i != ZEBRA_ROUTE_BGP) - bgp_redistribute_unset (bgp, afi, i, 0); - - /* Free peers and peer-groups. */ - for (ALL_LIST_ELEMENTS (bgp->group, node, next, group)) - peer_group_delete (group); - - for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer)) - peer_delete (peer); - - if (bgp->peer_self) { - peer_delete(bgp->peer_self); - bgp->peer_self = NULL; - } - - update_bgp_group_free (bgp); - - /* TODO - Other memory may need to be freed - e.g., NHT */ +int bgp_delete(struct bgp *bgp) +{ + struct peer *peer; + struct peer_group *group; + struct listnode *node, *next; + struct vrf *vrf; + afi_t afi; + int i; + + THREAD_OFF(bgp->t_startup); + + if (BGP_DEBUG(zebra, ZEBRA)) { + if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + zlog_debug("Deleting Default VRF"); + else + zlog_debug("Deleting %s %s", + (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) + ? "VRF" + : "VIEW", + bgp->name); + } + + /* Stop timers. */ + if (bgp->t_rmap_def_originate_eval) { + BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval); + bgp_unlock(bgp); /* TODO - This timer is started with a lock - + why? */ + } + + /* Inform peers we're going down. */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); + } + + /* Delete static routes (networks). */ + bgp_static_delete(bgp); + + /* Unset redistribution. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (i != ZEBRA_ROUTE_BGP) + bgp_redistribute_unset(bgp, afi, i, 0); + + /* Free peers and peer-groups. */ + for (ALL_LIST_ELEMENTS(bgp->group, node, next, group)) + peer_group_delete(group); + + for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) + peer_delete(peer); + + if (bgp->peer_self) { + peer_delete(bgp->peer_self); + bgp->peer_self = NULL; + } + + update_bgp_group_free(bgp); + +/* TODO - Other memory may need to be freed - e.g., NHT */ #if ENABLE_BGP_VNC - rfapi_delete(bgp); + rfapi_delete(bgp); #endif - bgp_cleanup_routes(bgp); + bgp_cleanup_routes(bgp); + + /* Remove visibility via the master list - there may however still be + * routes to be processed still referencing the struct bgp. + */ + listnode_delete(bm->bgp, bgp); - /* Remove visibility via the master list - there may however still be - * routes to be processed still referencing the struct bgp. - */ - listnode_delete (bm->bgp, bgp); + /* Deregister from Zebra, if needed */ + if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + bgp_zebra_instance_deregister(bgp); - /* Deregister from Zebra, if needed */ - if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) - bgp_zebra_instance_deregister (bgp); + /* Free interfaces in this instance. */ + bgp_if_finish(bgp); - /* Free interfaces in this instance. */ - bgp_if_finish (bgp); + vrf = bgp_vrf_lookup_by_instance_type(bgp); + if (vrf) + bgp_vrf_unlink(bgp, vrf); - vrf = bgp_vrf_lookup_by_instance_type (bgp); - if (vrf) - bgp_vrf_unlink (bgp, vrf); + thread_master_free_unused(bm->master); + bgp_unlock(bgp); /* initial reference */ - thread_master_free_unused(bm->master); - bgp_unlock(bgp); /* initial reference */ + return 0; +} + +static void bgp_free(struct bgp *); - return 0; +void bgp_lock(struct bgp *bgp) +{ + ++bgp->lock; } -static void bgp_free (struct bgp *); +void bgp_unlock(struct bgp *bgp) +{ + assert(bgp->lock > 0); + if (--bgp->lock == 0) + bgp_free(bgp); +} -void -bgp_lock (struct bgp *bgp) +static void bgp_free(struct bgp *bgp) { - ++bgp->lock; + afi_t afi; + safi_t safi; + struct bgp_table *table; + struct bgp_node *rn; + + QOBJ_UNREG(bgp); + + list_delete(bgp->group); + list_delete(bgp->peer); + + if (bgp->peerhash) { + hash_free(bgp->peerhash); + bgp->peerhash = NULL; + } + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + /* Special handling for 2-level routing tables. */ + if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP + || safi == SAFI_EVPN) { + for (rn = bgp_table_top(bgp->rib[afi][safi]); + rn; rn = bgp_route_next(rn)) { + table = (struct bgp_table *)rn->info; + bgp_table_finish(&table); + } + } + if (bgp->route[afi][safi]) + bgp_table_finish(&bgp->route[afi][safi]); + if (bgp->aggregate[afi][safi]) + bgp_table_finish(&bgp->aggregate[afi][safi]); + if (bgp->rib[afi][safi]) + bgp_table_finish(&bgp->rib[afi][safi]); + } + + bgp_scan_finish(bgp); + bgp_address_destroy(bgp); + + bgp_evpn_cleanup(bgp); + + if (bgp->name) + XFREE(MTYPE_BGP, bgp->name); + + XFREE(MTYPE_BGP, bgp); } -void -bgp_unlock(struct bgp *bgp) +struct peer *peer_lookup_by_conf_if(struct bgp *bgp, const char *conf_if) { - assert(bgp->lock > 0); - if (--bgp->lock == 0) - bgp_free (bgp); + struct peer *peer; + struct listnode *node, *nnode; + + if (!conf_if) + return NULL; + + if (bgp != NULL) { + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) + if (peer->conf_if && !strcmp(peer->conf_if, conf_if) + && !CHECK_FLAG(peer->sflags, + PEER_STATUS_ACCEPT_PEER)) + return peer; + } else if (bm->bgp != NULL) { + struct listnode *bgpnode, *nbgpnode; + + for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp)) + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) + if (peer->conf_if + && !strcmp(peer->conf_if, conf_if) + && !CHECK_FLAG(peer->sflags, + PEER_STATUS_ACCEPT_PEER)) + return peer; + } + return NULL; } - -static void -bgp_free (struct bgp *bgp) + +struct peer *peer_lookup_by_hostname(struct bgp *bgp, const char *hostname) { - afi_t afi; - safi_t safi; - struct bgp_table *table; - struct bgp_node *rn; - - QOBJ_UNREG (bgp); - - list_delete (bgp->group); - list_delete (bgp->peer); - - if (bgp->peerhash) - { - hash_free(bgp->peerhash); - bgp->peerhash = NULL; - } + struct peer *peer; + struct listnode *node, *nnode; + + if (!hostname) + return NULL; + + if (bgp != NULL) { + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) + if (peer->hostname && !strcmp(peer->hostname, hostname) + && !CHECK_FLAG(peer->sflags, + PEER_STATUS_ACCEPT_PEER)) + return peer; + } else if (bm->bgp != NULL) { + struct listnode *bgpnode, *nbgpnode; - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - /* Special handling for 2-level routing tables. */ - if (safi == SAFI_MPLS_VPN || - safi == SAFI_ENCAP || - safi == SAFI_EVPN) - { - for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; - rn = bgp_route_next (rn)) - { - table = (struct bgp_table *) rn->info; - bgp_table_finish(&table); - } - } - if (bgp->route[afi][safi]) - bgp_table_finish (&bgp->route[afi][safi]); - if (bgp->aggregate[afi][safi]) - bgp_table_finish (&bgp->aggregate[afi][safi]) ; - if (bgp->rib[afi][safi]) - bgp_table_finish (&bgp->rib[afi][safi]); - } - - bgp_scan_finish (bgp); - bgp_address_destroy (bgp); - - bgp_evpn_cleanup (bgp); - - if (bgp->name) - XFREE(MTYPE_BGP, bgp->name); - - XFREE (MTYPE_BGP, bgp); -} - -struct peer * -peer_lookup_by_conf_if (struct bgp *bgp, const char *conf_if) -{ - struct peer *peer; - struct listnode *node, *nnode; - - if (!conf_if) - return NULL; - - if (bgp != NULL) - { - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - if (peer->conf_if && !strcmp(peer->conf_if, conf_if) - && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) - return peer; - } - else if (bm->bgp != NULL) - { - struct listnode *bgpnode, *nbgpnode; - - for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp)) - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - if (peer->conf_if && !strcmp(peer->conf_if, conf_if) - && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) - return peer; - } - return NULL; -} - -struct peer * -peer_lookup_by_hostname (struct bgp *bgp, const char *hostname) -{ - struct peer *peer; - struct listnode *node, *nnode; - - if (!hostname) - return NULL; - - if (bgp != NULL) - { - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - if (peer->hostname && !strcmp(peer->hostname, hostname) - && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) - return peer; - } - else if (bm->bgp != NULL) - { - struct listnode *bgpnode, *nbgpnode; - - for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp)) - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - if (peer->hostname && !strcmp(peer->hostname, hostname) - && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) - return peer; - } - return NULL; -} - -struct peer * -peer_lookup (struct bgp *bgp, union sockunion *su) -{ - struct peer *peer = NULL; - struct peer tmp_peer; - - memset(&tmp_peer, 0, sizeof(struct peer)); - - /* - * We do not want to find the doppelganger peer so search for the peer in - * the hash that has PEER_FLAG_CONFIG_NODE - */ - SET_FLAG (tmp_peer.flags, PEER_FLAG_CONFIG_NODE); - - tmp_peer.su = *su; - - if (bgp != NULL) - { - peer = hash_lookup(bgp->peerhash, &tmp_peer); - } - else if (bm->bgp != NULL) - { - struct listnode *bgpnode, *nbgpnode; - - for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp)) - { - /* Skip VRFs, this function will not be invoked without an instance - * when examining VRFs. - */ - if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) - continue; - - peer = hash_lookup(bgp->peerhash, &tmp_peer); - - if (peer) - break; - } - } - - return peer; -} - -struct peer * -peer_create_bind_dynamic_neighbor (struct bgp *bgp, union sockunion *su, - struct peer_group *group) -{ - struct peer *peer; - afi_t afi; - safi_t safi; - - /* Create peer first; we've already checked group config is valid. */ - peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, group->conf->as_type, 0, 0, group); - if (!peer) - return NULL; - - /* Link to group */ - peer = peer_lock (peer); - listnode_add (group->peer, peer); - - peer_group2peer_config_copy(group, peer); - - /* - * Bind peer for all AFs configured for the group. We don't call - * peer_group_bind as that is sub-optimal and does some stuff we don't want. - */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - if (!group->conf->afc[afi][safi]) - continue; - peer->afc[afi][safi] = 1; - - if (!peer_af_find(peer, afi, safi)) - peer_af_create(peer, afi, safi); - - peer_group2peer_config_copy_af (group, peer, afi, safi); - } - - /* Mark as dynamic, but also as a "config node" for other things to work. */ - SET_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR); - SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); - - return peer; + for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp)) + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) + if (peer->hostname + && !strcmp(peer->hostname, hostname) + && !CHECK_FLAG(peer->sflags, + PEER_STATUS_ACCEPT_PEER)) + return peer; + } + return NULL; +} + +struct peer *peer_lookup(struct bgp *bgp, union sockunion *su) +{ + struct peer *peer = NULL; + struct peer tmp_peer; + + memset(&tmp_peer, 0, sizeof(struct peer)); + + /* + * We do not want to find the doppelganger peer so search for the peer + * in + * the hash that has PEER_FLAG_CONFIG_NODE + */ + SET_FLAG(tmp_peer.flags, PEER_FLAG_CONFIG_NODE); + + tmp_peer.su = *su; + + if (bgp != NULL) { + peer = hash_lookup(bgp->peerhash, &tmp_peer); + } else if (bm->bgp != NULL) { + struct listnode *bgpnode, *nbgpnode; + + for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp)) { + /* Skip VRFs, this function will not be invoked without + * an instance + * when examining VRFs. + */ + if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) + continue; + + peer = hash_lookup(bgp->peerhash, &tmp_peer); + + if (peer) + break; + } + } + + return peer; +} + +struct peer *peer_create_bind_dynamic_neighbor(struct bgp *bgp, + union sockunion *su, + struct peer_group *group) +{ + struct peer *peer; + afi_t afi; + safi_t safi; + + /* Create peer first; we've already checked group config is valid. */ + peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as, + group->conf->as_type, 0, 0, group); + if (!peer) + return NULL; + + /* Link to group */ + peer = peer_lock(peer); + listnode_add(group->peer, peer); + + peer_group2peer_config_copy(group, peer); + + /* + * Bind peer for all AFs configured for the group. We don't call + * peer_group_bind as that is sub-optimal and does some stuff we don't + * want. + */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + if (!group->conf->afc[afi][safi]) + continue; + peer->afc[afi][safi] = 1; + + if (!peer_af_find(peer, afi, safi)) + peer_af_create(peer, afi, safi); + + peer_group2peer_config_copy_af(group, peer, afi, safi); + } + + /* Mark as dynamic, but also as a "config node" for other things to + * work. */ + SET_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR); + SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); + + return peer; } struct prefix * -peer_group_lookup_dynamic_neighbor_range (struct peer_group * group, - struct prefix * prefix) +peer_group_lookup_dynamic_neighbor_range(struct peer_group *group, + struct prefix *prefix) { - struct listnode *node, *nnode; - struct prefix *range; - afi_t afi; + struct listnode *node, *nnode; + struct prefix *range; + afi_t afi; - afi = family2afi(prefix->family); + afi = family2afi(prefix->family); - if (group->listen_range[afi]) - for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, range)) - if (prefix_match(range, prefix)) - return range; + if (group->listen_range[afi]) + for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode, + range)) + if (prefix_match(range, prefix)) + return range; - return NULL; + return NULL; } struct peer_group * -peer_group_lookup_dynamic_neighbor (struct bgp *bgp, struct prefix *prefix, - struct prefix **listen_range) -{ - struct prefix *range = NULL; - struct peer_group *group = NULL; - struct listnode *node, *nnode; - - *listen_range = NULL; - if (bgp != NULL) - { - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - if ((range = peer_group_lookup_dynamic_neighbor_range(group, prefix))) - break; - } - else if (bm->bgp != NULL) - { - struct listnode *bgpnode, *nbgpnode; - - for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp)) - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - if ((range = peer_group_lookup_dynamic_neighbor_range(group, prefix))) - goto found_range; - } +peer_group_lookup_dynamic_neighbor(struct bgp *bgp, struct prefix *prefix, + struct prefix **listen_range) +{ + struct prefix *range = NULL; + struct peer_group *group = NULL; + struct listnode *node, *nnode; + + *listen_range = NULL; + if (bgp != NULL) { + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) + if ((range = peer_group_lookup_dynamic_neighbor_range( + group, prefix))) + break; + } else if (bm->bgp != NULL) { + struct listnode *bgpnode, *nbgpnode; + + for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp)) + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) + if ((range = peer_group_lookup_dynamic_neighbor_range( + group, prefix))) + goto found_range; + } - found_range: - *listen_range = range; - return (group && range) ? group : NULL; +found_range: + *listen_range = range; + return (group && range) ? group : NULL; } -struct peer * -peer_lookup_dynamic_neighbor (struct bgp *bgp, union sockunion *su) +struct peer *peer_lookup_dynamic_neighbor(struct bgp *bgp, union sockunion *su) { - struct peer_group *group; - struct bgp *gbgp; - struct peer *peer; - struct prefix prefix; - struct prefix *listen_range; - int dncount; - char buf[PREFIX2STR_BUFFER]; - char buf1[PREFIX2STR_BUFFER]; + struct peer_group *group; + struct bgp *gbgp; + struct peer *peer; + struct prefix prefix; + struct prefix *listen_range; + int dncount; + char buf[PREFIX2STR_BUFFER]; + char buf1[PREFIX2STR_BUFFER]; - sockunion2hostprefix(su, &prefix); + sockunion2hostprefix(su, &prefix); - /* See if incoming connection matches a configured listen range. */ - group = peer_group_lookup_dynamic_neighbor (bgp, &prefix, &listen_range); + /* See if incoming connection matches a configured listen range. */ + group = peer_group_lookup_dynamic_neighbor(bgp, &prefix, &listen_range); - if (! group) - return NULL; + if (!group) + return NULL; - gbgp = group->bgp; + gbgp = group->bgp; - if (! gbgp) - return NULL; + if (!gbgp) + return NULL; - prefix2str(&prefix, buf, sizeof(buf)); - prefix2str(listen_range, buf1, sizeof(buf1)); + prefix2str(&prefix, buf, sizeof(buf)); + prefix2str(listen_range, buf1, sizeof(buf1)); - if (bgp_debug_neighbor_events(NULL)) - zlog_debug ("Dynamic Neighbor %s matches group %s listen range %s", - buf, group->name, buf1); + if (bgp_debug_neighbor_events(NULL)) + zlog_debug( + "Dynamic Neighbor %s matches group %s listen range %s", + buf, group->name, buf1); - /* Are we within the listen limit? */ - dncount = gbgp->dynamic_neighbors_count; + /* Are we within the listen limit? */ + dncount = gbgp->dynamic_neighbors_count; - if (dncount >= gbgp->dynamic_neighbors_limit) - { - if (bgp_debug_neighbor_events(NULL)) - zlog_debug ("Dynamic Neighbor %s rejected - at limit %d", - inet_sutop (su, buf), gbgp->dynamic_neighbors_limit); - return NULL; - } + if (dncount >= gbgp->dynamic_neighbors_limit) { + if (bgp_debug_neighbor_events(NULL)) + zlog_debug("Dynamic Neighbor %s rejected - at limit %d", + inet_sutop(su, buf), + gbgp->dynamic_neighbors_limit); + return NULL; + } - /* Ensure group is not disabled. */ - if (CHECK_FLAG (group->conf->flags, PEER_FLAG_SHUTDOWN)) - { - if (bgp_debug_neighbor_events(NULL)) - zlog_debug ("Dynamic Neighbor %s rejected - group %s disabled", - buf, group->name); - return NULL; - } + /* Ensure group is not disabled. */ + if (CHECK_FLAG(group->conf->flags, PEER_FLAG_SHUTDOWN)) { + if (bgp_debug_neighbor_events(NULL)) + zlog_debug( + "Dynamic Neighbor %s rejected - group %s disabled", + buf, group->name); + return NULL; + } - /* Check that at least one AF is activated for the group. */ - if (!peer_group_af_configured (group)) - { - if (bgp_debug_neighbor_events(NULL)) - zlog_debug ("Dynamic Neighbor %s rejected - no AF activated for group %s", - buf, group->name); - return NULL; - } + /* Check that at least one AF is activated for the group. */ + if (!peer_group_af_configured(group)) { + if (bgp_debug_neighbor_events(NULL)) + zlog_debug( + "Dynamic Neighbor %s rejected - no AF activated for group %s", + buf, group->name); + return NULL; + } - /* Create dynamic peer and bind to associated group. */ - peer = peer_create_bind_dynamic_neighbor (gbgp, su, group); - assert (peer); + /* Create dynamic peer and bind to associated group. */ + peer = peer_create_bind_dynamic_neighbor(gbgp, su, group); + assert(peer); - gbgp->dynamic_neighbors_count = ++dncount; + gbgp->dynamic_neighbors_count = ++dncount; - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Dynamic Neighbor added, group %s count %d", - peer->host, group->name, dncount); + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s Dynamic Neighbor added, group %s count %d", + peer->host, group->name, dncount); - return peer; + return peer; } - -void peer_drop_dynamic_neighbor (struct peer *peer) + +void peer_drop_dynamic_neighbor(struct peer *peer) { - int dncount = -1; - if (peer->group && peer->group->bgp) - { - dncount = peer->group->bgp->dynamic_neighbors_count; - if (dncount) - peer->group->bgp->dynamic_neighbors_count = --dncount; - } - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s dropped from group %s, count %d", - peer->host, peer->group->name, dncount); + int dncount = -1; + if (peer->group && peer->group->bgp) { + dncount = peer->group->bgp->dynamic_neighbors_count; + if (dncount) + peer->group->bgp->dynamic_neighbors_count = --dncount; + } + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s dropped from group %s, count %d", peer->host, + peer->group->name, dncount); } /* If peer is configured at least one address family return 1. */ -int -peer_active (struct peer *peer) -{ - if (BGP_PEER_SU_UNSPEC(peer)) - return 0; - if (peer->afc[AFI_IP][SAFI_UNICAST] - || peer->afc[AFI_IP][SAFI_MULTICAST] - || peer->afc[AFI_IP][SAFI_LABELED_UNICAST] - || peer->afc[AFI_IP][SAFI_MPLS_VPN] - || peer->afc[AFI_IP][SAFI_ENCAP] - || peer->afc[AFI_IP6][SAFI_UNICAST] - || peer->afc[AFI_IP6][SAFI_MULTICAST] - || peer->afc[AFI_IP6][SAFI_LABELED_UNICAST] - || peer->afc[AFI_IP6][SAFI_MPLS_VPN] - || peer->afc[AFI_IP6][SAFI_ENCAP] - || peer->afc[AFI_L2VPN][SAFI_EVPN]) - return 1; - return 0; +int peer_active(struct peer *peer) +{ + if (BGP_PEER_SU_UNSPEC(peer)) + return 0; + if (peer->afc[AFI_IP][SAFI_UNICAST] || peer->afc[AFI_IP][SAFI_MULTICAST] + || peer->afc[AFI_IP][SAFI_LABELED_UNICAST] + || peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_ENCAP] + || peer->afc[AFI_IP6][SAFI_UNICAST] + || peer->afc[AFI_IP6][SAFI_MULTICAST] + || peer->afc[AFI_IP6][SAFI_LABELED_UNICAST] + || peer->afc[AFI_IP6][SAFI_MPLS_VPN] + || peer->afc[AFI_IP6][SAFI_ENCAP] + || peer->afc[AFI_L2VPN][SAFI_EVPN]) + return 1; + return 0; } /* If peer is negotiated at least one address family return 1. */ -int -peer_active_nego (struct peer *peer) -{ - if (peer->afc_nego[AFI_IP][SAFI_UNICAST] - || peer->afc_nego[AFI_IP][SAFI_MULTICAST] - || peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST] - || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] - || peer->afc_nego[AFI_IP][SAFI_ENCAP] - || peer->afc_nego[AFI_IP6][SAFI_UNICAST] - || peer->afc_nego[AFI_IP6][SAFI_MULTICAST] - || peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST] - || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] - || peer->afc_nego[AFI_IP6][SAFI_ENCAP] - || peer->afc_nego[AFI_L2VPN][SAFI_EVPN]) - return 1; - return 0; +int peer_active_nego(struct peer *peer) +{ + if (peer->afc_nego[AFI_IP][SAFI_UNICAST] + || peer->afc_nego[AFI_IP][SAFI_MULTICAST] + || peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST] + || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] + || peer->afc_nego[AFI_IP][SAFI_ENCAP] + || peer->afc_nego[AFI_IP6][SAFI_UNICAST] + || peer->afc_nego[AFI_IP6][SAFI_MULTICAST] + || peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST] + || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] + || peer->afc_nego[AFI_IP6][SAFI_ENCAP] + || peer->afc_nego[AFI_L2VPN][SAFI_EVPN]) + return 1; + return 0; } /* peer_flag_change_type. */ -enum peer_change_type -{ - peer_change_none, - peer_change_reset, - peer_change_reset_in, - peer_change_reset_out, +enum peer_change_type { + peer_change_none, + peer_change_reset, + peer_change_reset_in, + peer_change_reset_out, }; -static void -peer_change_action (struct peer *peer, afi_t afi, safi_t safi, - enum peer_change_type type) -{ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return; - - if (peer->status != Established) - return; - - if (type == peer_change_reset) - { - /* If we're resetting session, we've to delete both peer struct */ - if ((peer->doppelganger) && (peer->doppelganger->status != Deleted) - && (!CHECK_FLAG(peer->doppelganger->flags, - PEER_FLAG_CONFIG_NODE))) - peer_delete(peer->doppelganger); - - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else if (type == peer_change_reset_in) - { - if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV) - || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV)) - bgp_route_refresh_send (peer, afi, safi, 0, 0, 0); - else - { - if ((peer->doppelganger) && (peer->doppelganger->status != Deleted) - && (!CHECK_FLAG(peer->doppelganger->flags, - PEER_FLAG_CONFIG_NODE))) - peer_delete(peer->doppelganger); - - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); +static void peer_change_action(struct peer *peer, afi_t afi, safi_t safi, + enum peer_change_type type) +{ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return; + + if (peer->status != Established) + return; + + if (type == peer_change_reset) { + /* If we're resetting session, we've to delete both peer struct + */ + if ((peer->doppelganger) + && (peer->doppelganger->status != Deleted) + && (!CHECK_FLAG(peer->doppelganger->flags, + PEER_FLAG_CONFIG_NODE))) + peer_delete(peer->doppelganger); + + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else if (type == peer_change_reset_in) { + if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV) + || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV)) + bgp_route_refresh_send(peer, afi, safi, 0, 0, 0); + else { + if ((peer->doppelganger) + && (peer->doppelganger->status != Deleted) + && (!CHECK_FLAG(peer->doppelganger->flags, + PEER_FLAG_CONFIG_NODE))) + peer_delete(peer->doppelganger); + + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } + } else if (type == peer_change_reset_out) { + update_group_adjust_peer(peer_af_find(peer, afi, safi)); + bgp_announce_route(peer, afi, safi); } - } - else if (type == peer_change_reset_out) - { - update_group_adjust_peer(peer_af_find(peer, afi, safi)); - bgp_announce_route (peer, afi, safi); - } } -struct peer_flag_action -{ - /* Peer's flag. */ - u_int32_t flag; +struct peer_flag_action { + /* Peer's flag. */ + u_int32_t flag; - /* This flag can be set for peer-group member. */ - u_char not_for_member; + /* This flag can be set for peer-group member. */ + u_char not_for_member; - /* Action when the flag is changed. */ - enum peer_change_type type; + /* Action when the flag is changed. */ + enum peer_change_type type; - /* Peer down cause */ - u_char peer_down; + /* Peer down cause */ + u_char peer_down; }; -static const struct peer_flag_action peer_flag_action_list[] = - { - { PEER_FLAG_PASSIVE, 0, peer_change_reset }, - { PEER_FLAG_SHUTDOWN, 0, peer_change_reset }, - { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none }, - { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none }, - { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none }, - { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset }, - { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset }, - { PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset }, - { 0, 0, 0 } - }; - -static const struct peer_flag_action peer_af_flag_action_list[] = - { - { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out }, - { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out }, - { PEER_FLAG_SEND_LARGE_COMMUNITY, 1, peer_change_reset_out }, - { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out }, - { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset }, - { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset }, - { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in }, - { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out }, - { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out }, - { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out }, - // PEER_FLAG_DEFAULT_ORIGINATE - { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out }, - { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in }, - { PEER_FLAG_ALLOWAS_IN_ORIGIN, 0, peer_change_reset_in }, - { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset }, - { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset }, - // PEER_FLAG_MAX_PREFIX - // PEER_FLAG_MAX_PREFIX_WARNING - { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out }, - { PEER_FLAG_FORCE_NEXTHOP_SELF, 1, peer_change_reset_out }, - { PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out }, - { PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE,1, peer_change_reset_out }, - { PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out }, - { PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE,1, peer_change_reset_out }, - { PEER_FLAG_ADDPATH_TX_ALL_PATHS, 1, peer_change_reset }, - { PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS, 1, peer_change_reset }, - { PEER_FLAG_WEIGHT, 0, peer_change_reset_in }, - { 0, 0, 0 } - }; +static const struct peer_flag_action peer_flag_action_list[] = { + {PEER_FLAG_PASSIVE, 0, peer_change_reset}, + {PEER_FLAG_SHUTDOWN, 0, peer_change_reset}, + {PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none}, + {PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none}, + {PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none}, + {PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset}, + {PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset}, + {PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset}, + {0, 0, 0}}; + +static const struct peer_flag_action peer_af_flag_action_list[] = { + {PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out}, + {PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out}, + {PEER_FLAG_SEND_LARGE_COMMUNITY, 1, peer_change_reset_out}, + {PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out}, + {PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset}, + {PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset}, + {PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in}, + {PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out}, + {PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out}, + {PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out}, + // PEER_FLAG_DEFAULT_ORIGINATE + {PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out}, + {PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in}, + {PEER_FLAG_ALLOWAS_IN_ORIGIN, 0, peer_change_reset_in}, + {PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset}, + {PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset}, + // PEER_FLAG_MAX_PREFIX + // PEER_FLAG_MAX_PREFIX_WARNING + {PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out}, + {PEER_FLAG_FORCE_NEXTHOP_SELF, 1, peer_change_reset_out}, + {PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out}, + {PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE, 1, peer_change_reset_out}, + {PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out}, + {PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE, 1, peer_change_reset_out}, + {PEER_FLAG_ADDPATH_TX_ALL_PATHS, 1, peer_change_reset}, + {PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS, 1, peer_change_reset}, + {PEER_FLAG_WEIGHT, 0, peer_change_reset_in}, + {0, 0, 0}}; /* Proper action set. */ -static int -peer_flag_action_set (const struct peer_flag_action *action_list, int size, - struct peer_flag_action *action, u_int32_t flag) -{ - int i; - int found = 0; - int reset_in = 0; - int reset_out = 0; - const struct peer_flag_action *match = NULL; - - /* Check peer's frag action. */ - for (i = 0; i < size; i++) - { - match = &action_list[i]; - - if (match->flag == 0) - break; +static int peer_flag_action_set(const struct peer_flag_action *action_list, + int size, struct peer_flag_action *action, + u_int32_t flag) +{ + int i; + int found = 0; + int reset_in = 0; + int reset_out = 0; + const struct peer_flag_action *match = NULL; + + /* Check peer's frag action. */ + for (i = 0; i < size; i++) { + match = &action_list[i]; + + if (match->flag == 0) + break; + + if (match->flag & flag) { + found = 1; + + if (match->type == peer_change_reset_in) + reset_in = 1; + if (match->type == peer_change_reset_out) + reset_out = 1; + if (match->type == peer_change_reset) { + reset_in = 1; + reset_out = 1; + } + if (match->not_for_member) + action->not_for_member = 1; + } + } - if (match->flag & flag) - { - found = 1; - - if (match->type == peer_change_reset_in) - reset_in = 1; - if (match->type == peer_change_reset_out) - reset_out = 1; - if (match->type == peer_change_reset) - { - reset_in = 1; - reset_out = 1; - } - if (match->not_for_member) - action->not_for_member = 1; - } - } - - /* Set peer clear type. */ - if (reset_in && reset_out) - action->type = peer_change_reset; - else if (reset_in) - action->type = peer_change_reset_in; - else if (reset_out) - action->type = peer_change_reset_out; - else - action->type = peer_change_none; - - return found; -} - -static void -peer_flag_modify_action (struct peer *peer, u_int32_t flag) -{ - if (flag == PEER_FLAG_SHUTDOWN) - { - if (CHECK_FLAG (peer->flags, flag)) - { - if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT)) - peer_nsf_stop (peer); - - UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW); - if (peer->t_pmax_restart) - { - BGP_TIMER_OFF (peer->t_pmax_restart); - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Maximum-prefix restart timer canceled", - peer->host); - } - - if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT)) - peer_nsf_stop (peer); - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - char *msg = peer->tx_shutdown_message; - size_t msglen; - - if (!msg && peer_group_active (peer)) - msg = peer->group->conf->tx_shutdown_message; - msglen = msg ? strlen(msg) : 0; - if (msglen > 128) - msglen = 128; - - if (msglen) - { - u_char msgbuf[129]; - - msgbuf[0] = msglen; - memcpy(msgbuf + 1, msg, msglen); - - bgp_notify_send_with_data (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN, - msgbuf, msglen + 1); - } - else - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); - } - else - bgp_session_reset(peer); - } - else - { - peer->v_start = BGP_INIT_START_TIMER; - BGP_EVENT_ADD (peer, BGP_Stop); - } - } - else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - if (flag == PEER_FLAG_DYNAMIC_CAPABILITY) - peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; - else if (flag == PEER_FLAG_PASSIVE) - peer->last_reset = PEER_DOWN_PASSIVE_CHANGE; - else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK) - peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE; - - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); + /* Set peer clear type. */ + if (reset_in && reset_out) + action->type = peer_change_reset; + else if (reset_in) + action->type = peer_change_reset_in; + else if (reset_out) + action->type = peer_change_reset_out; + else + action->type = peer_change_none; + + return found; +} + +static void peer_flag_modify_action(struct peer *peer, u_int32_t flag) +{ + if (flag == PEER_FLAG_SHUTDOWN) { + if (CHECK_FLAG(peer->flags, flag)) { + if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) + peer_nsf_stop(peer); + + UNSET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW); + if (peer->t_pmax_restart) { + BGP_TIMER_OFF(peer->t_pmax_restart); + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Maximum-prefix restart timer canceled", + peer->host); + } + + if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) + peer_nsf_stop(peer); + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + char *msg = peer->tx_shutdown_message; + size_t msglen; + + if (!msg && peer_group_active(peer)) + msg = peer->group->conf + ->tx_shutdown_message; + msglen = msg ? strlen(msg) : 0; + if (msglen > 128) + msglen = 128; + + if (msglen) { + u_char msgbuf[129]; + + msgbuf[0] = msglen; + memcpy(msgbuf + 1, msg, msglen); + + bgp_notify_send_with_data( + peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN, + msgbuf, msglen + 1); + } else + bgp_notify_send( + peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); + } else + bgp_session_reset(peer); + } else { + peer->v_start = BGP_INIT_START_TIMER; + BGP_EVENT_ADD(peer, BGP_Stop); + } + } else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + if (flag == PEER_FLAG_DYNAMIC_CAPABILITY) + peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; + else if (flag == PEER_FLAG_PASSIVE) + peer->last_reset = PEER_DOWN_PASSIVE_CHANGE; + else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK) + peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE; + + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); } /* Change specified peer flag. */ -static int -peer_flag_modify (struct peer *peer, u_int32_t flag, int set) -{ - int found; - int size; - struct peer_group *group; - struct peer *tmp_peer; - struct listnode *node, *nnode; - struct peer_flag_action action; - - memset (&action, 0, sizeof (struct peer_flag_action)); - size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action); - - found = peer_flag_action_set (peer_flag_action_list, size, &action, flag); - - /* No flag action is found. */ - if (! found) - return BGP_ERR_INVALID_FLAG; - - /* When unset the peer-group member's flag we have to check - peer-group configuration. */ - if (! set && peer_group_active (peer)) - if (CHECK_FLAG (peer->group->conf->flags, flag)) - { - if (flag == PEER_FLAG_SHUTDOWN) - return BGP_ERR_PEER_GROUP_SHUTDOWN; - } - - /* Flag conflict check. */ - if (set - && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH) - && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY)) - return BGP_ERR_PEER_FLAG_CONFLICT; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (set && CHECK_FLAG (peer->flags, flag) == flag) - return 0; - if (! set && ! CHECK_FLAG (peer->flags, flag)) - return 0; - } +static int peer_flag_modify(struct peer *peer, u_int32_t flag, int set) +{ + int found; + int size; + struct peer_group *group; + struct peer *tmp_peer; + struct listnode *node, *nnode; + struct peer_flag_action action; + + memset(&action, 0, sizeof(struct peer_flag_action)); + size = sizeof peer_flag_action_list / sizeof(struct peer_flag_action); + + found = peer_flag_action_set(peer_flag_action_list, size, &action, + flag); + + /* No flag action is found. */ + if (!found) + return BGP_ERR_INVALID_FLAG; + + /* When unset the peer-group member's flag we have to check + peer-group configuration. */ + if (!set && peer_group_active(peer)) + if (CHECK_FLAG(peer->group->conf->flags, flag)) { + if (flag == PEER_FLAG_SHUTDOWN) + return BGP_ERR_PEER_GROUP_SHUTDOWN; + } - if (set) - SET_FLAG (peer->flags, flag); - else - UNSET_FLAG (peer->flags, flag); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (action.type == peer_change_reset) - peer_flag_modify_action (peer, flag); + /* Flag conflict check. */ + if (set && CHECK_FLAG(peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH) + && CHECK_FLAG(peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY)) + return BGP_ERR_PEER_FLAG_CONFLICT; - return 0; - } + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (set && CHECK_FLAG(peer->flags, flag) == flag) + return 0; + if (!set && !CHECK_FLAG(peer->flags, flag)) + return 0; + } - /* peer-group member updates. */ - group = peer->group; + if (set) + SET_FLAG(peer->flags, flag); + else + UNSET_FLAG(peer->flags, flag); - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer)) - { + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (action.type == peer_change_reset) + peer_flag_modify_action(peer, flag); - if (set && CHECK_FLAG (tmp_peer->flags, flag) == flag) - continue; + return 0; + } - if (! set && ! CHECK_FLAG (tmp_peer->flags, flag)) - continue; + /* peer-group member updates. */ + group = peer->group; - if (set) - SET_FLAG (tmp_peer->flags, flag); - else - UNSET_FLAG (tmp_peer->flags, flag); + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) { - if (action.type == peer_change_reset) - peer_flag_modify_action (tmp_peer, flag); - } - return 0; + if (set && CHECK_FLAG(tmp_peer->flags, flag) == flag) + continue; + + if (!set && !CHECK_FLAG(tmp_peer->flags, flag)) + continue; + + if (set) + SET_FLAG(tmp_peer->flags, flag); + else + UNSET_FLAG(tmp_peer->flags, flag); + + if (action.type == peer_change_reset) + peer_flag_modify_action(tmp_peer, flag); + } + return 0; } -int -peer_flag_set (struct peer *peer, u_int32_t flag) +int peer_flag_set(struct peer *peer, u_int32_t flag) { - return peer_flag_modify (peer, flag, 1); + return peer_flag_modify(peer, flag, 1); } -int -peer_flag_unset (struct peer *peer, u_int32_t flag) +int peer_flag_unset(struct peer *peer, u_int32_t flag) { - return peer_flag_modify (peer, flag, 0); + return peer_flag_modify(peer, flag, 0); } -static int -peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag, - int set) +static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi, + u_int32_t flag, int set) { - int found; - int size; - struct listnode *node, *nnode; - struct peer_group *group; - struct peer_flag_action action; - struct peer *tmp_peer; - struct bgp *bgp; - int addpath_tx_used; - - memset (&action, 0, sizeof (struct peer_flag_action)); - size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action); - - found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag); - - /* No flag action is found. */ - if (! found) - return BGP_ERR_INVALID_FLAG; + int found; + int size; + struct listnode *node, *nnode; + struct peer_group *group; + struct peer_flag_action action; + struct peer *tmp_peer; + struct bgp *bgp; + int addpath_tx_used; - /* Special check for reflector client. */ - if (flag & PEER_FLAG_REFLECTOR_CLIENT - && peer_sort (peer) != BGP_PEER_IBGP) - return BGP_ERR_NOT_INTERNAL_PEER; + memset(&action, 0, sizeof(struct peer_flag_action)); + size = sizeof peer_af_flag_action_list + / sizeof(struct peer_flag_action); - /* Special check for remove-private-AS. */ - if (flag & PEER_FLAG_REMOVE_PRIVATE_AS - && peer_sort (peer) == BGP_PEER_IBGP) - return BGP_ERR_REMOVE_PRIVATE_AS; + found = peer_flag_action_set(peer_af_flag_action_list, size, &action, + flag); - /* as-override is not allowed for IBGP peers */ - if (flag & PEER_FLAG_AS_OVERRIDE - && peer_sort (peer) == BGP_PEER_IBGP) - return BGP_ERR_AS_OVERRIDE; - - /* When current flag configuration is same as requested one. */ - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag) - return 0; - if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag)) - return 0; - } - - if (set) - SET_FLAG (peer->af_flags[afi][safi], flag); - else - UNSET_FLAG (peer->af_flags[afi][safi], flag); - - /* Execute action when peer is established. */ - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP) - && peer->status == Established) - { - if (! set && flag == PEER_FLAG_SOFT_RECONFIG) - bgp_clear_adj_in (peer, afi, safi); - else - { - if (flag == PEER_FLAG_REFLECTOR_CLIENT) - peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE; - else if (flag == PEER_FLAG_RSERVER_CLIENT) - peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE; - else if (flag == PEER_FLAG_ORF_PREFIX_SM) - peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; - else if (flag == PEER_FLAG_ORF_PREFIX_RM) - peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; - - peer_change_action (peer, afi, safi, action.type); - } - - } - - /* Peer group member updates. */ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - group = peer->group; - - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer)) - { - if (set && CHECK_FLAG (tmp_peer->af_flags[afi][safi], flag) == flag) - continue; + /* No flag action is found. */ + if (!found) + return BGP_ERR_INVALID_FLAG; - if (! set && ! CHECK_FLAG (tmp_peer->af_flags[afi][safi], flag)) - continue; + /* Special check for reflector client. */ + if (flag & PEER_FLAG_REFLECTOR_CLIENT + && peer_sort(peer) != BGP_PEER_IBGP) + return BGP_ERR_NOT_INTERNAL_PEER; - if (set) - SET_FLAG (tmp_peer->af_flags[afi][safi], flag); - else - UNSET_FLAG (tmp_peer->af_flags[afi][safi], flag); + /* Special check for remove-private-AS. */ + if (flag & PEER_FLAG_REMOVE_PRIVATE_AS + && peer_sort(peer) == BGP_PEER_IBGP) + return BGP_ERR_REMOVE_PRIVATE_AS; - if (tmp_peer->status == Established) - { - if (! set && flag == PEER_FLAG_SOFT_RECONFIG) - bgp_clear_adj_in (tmp_peer, afi, safi); - else - { - if (flag == PEER_FLAG_REFLECTOR_CLIENT) - tmp_peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE; - else if (flag == PEER_FLAG_RSERVER_CLIENT) - tmp_peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE; - else if (flag == PEER_FLAG_ORF_PREFIX_SM) - tmp_peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; - else if (flag == PEER_FLAG_ORF_PREFIX_RM) - tmp_peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; + /* as-override is not allowed for IBGP peers */ + if (flag & PEER_FLAG_AS_OVERRIDE && peer_sort(peer) == BGP_PEER_IBGP) + return BGP_ERR_AS_OVERRIDE; - peer_change_action (tmp_peer, afi, safi, action.type); - } - } + /* When current flag configuration is same as requested one. */ + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (set && CHECK_FLAG(peer->af_flags[afi][safi], flag) == flag) + return 0; + if (!set && !CHECK_FLAG(peer->af_flags[afi][safi], flag)) + return 0; } - } - /* Track if addpath TX is in use */ - if (flag & (PEER_FLAG_ADDPATH_TX_ALL_PATHS|PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) - { - bgp = peer->bgp; - addpath_tx_used = 0; + if (set) + SET_FLAG(peer->af_flags[afi][safi], flag); + else + UNSET_FLAG(peer->af_flags[afi][safi], flag); + + /* Execute action when peer is established. */ + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) + && peer->status == Established) { + if (!set && flag == PEER_FLAG_SOFT_RECONFIG) + bgp_clear_adj_in(peer, afi, safi); + else { + if (flag == PEER_FLAG_REFLECTOR_CLIENT) + peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE; + else if (flag == PEER_FLAG_RSERVER_CLIENT) + peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE; + else if (flag == PEER_FLAG_ORF_PREFIX_SM) + peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; + else if (flag == PEER_FLAG_ORF_PREFIX_RM) + peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; + + peer_change_action(peer, afi, safi, action.type); + } + } - if (set) - { - addpath_tx_used = 1; + /* Peer group member updates. */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + group = peer->group; + + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) { + if (set + && CHECK_FLAG(tmp_peer->af_flags[afi][safi], flag) + == flag) + continue; + + if (!set + && !CHECK_FLAG(tmp_peer->af_flags[afi][safi], flag)) + continue; + + if (set) + SET_FLAG(tmp_peer->af_flags[afi][safi], flag); + else + UNSET_FLAG(tmp_peer->af_flags[afi][safi], flag); + + if (tmp_peer->status == Established) { + if (!set && flag == PEER_FLAG_SOFT_RECONFIG) + bgp_clear_adj_in(tmp_peer, afi, safi); + else { + if (flag == PEER_FLAG_REFLECTOR_CLIENT) + tmp_peer->last_reset = + PEER_DOWN_RR_CLIENT_CHANGE; + else if (flag + == PEER_FLAG_RSERVER_CLIENT) + tmp_peer->last_reset = + PEER_DOWN_RS_CLIENT_CHANGE; + else if (flag + == PEER_FLAG_ORF_PREFIX_SM) + tmp_peer->last_reset = + PEER_DOWN_CAPABILITY_CHANGE; + else if (flag + == PEER_FLAG_ORF_PREFIX_RM) + tmp_peer->last_reset = + PEER_DOWN_CAPABILITY_CHANGE; + + peer_change_action(tmp_peer, afi, safi, + action.type); + } + } + } + } - if (flag & PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS) - { - if (!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)) - { - zlog_warn("%s: enabling bgp deterministic-med, this is required"\ - " for addpath-tx-bestpath-per-AS", - peer->host); - bgp_flag_set (bgp, BGP_FLAG_DETERMINISTIC_MED); - bgp_recalculate_all_bestpaths (bgp); - } - } - } - else - { - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, tmp_peer)) - { - if (CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS) || - CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) - { - addpath_tx_used = 1; - break; - } - } - } + /* Track if addpath TX is in use */ + if (flag & (PEER_FLAG_ADDPATH_TX_ALL_PATHS + | PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) { + bgp = peer->bgp; + addpath_tx_used = 0; + + if (set) { + addpath_tx_used = 1; + + if (flag & PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS) { + if (!bgp_flag_check( + bgp, BGP_FLAG_DETERMINISTIC_MED)) { + zlog_warn( + "%s: enabling bgp deterministic-med, this is required" + " for addpath-tx-bestpath-per-AS", + peer->host); + bgp_flag_set( + bgp, + BGP_FLAG_DETERMINISTIC_MED); + bgp_recalculate_all_bestpaths(bgp); + } + } + } else { + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, + tmp_peer)) { + if (CHECK_FLAG(tmp_peer->af_flags[afi][safi], + PEER_FLAG_ADDPATH_TX_ALL_PATHS) + || CHECK_FLAG( + tmp_peer->af_flags[afi][safi], + PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) { + addpath_tx_used = 1; + break; + } + } + } - bgp->addpath_tx_used[afi][safi] = addpath_tx_used; - } + bgp->addpath_tx_used[afi][safi] = addpath_tx_used; + } - return 0; + return 0; } -int -peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag) +int peer_af_flag_set(struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag) { - return peer_af_flag_modify (peer, afi, safi, flag, 1); + return peer_af_flag_modify(peer, afi, safi, flag, 1); } -int -peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag) +int peer_af_flag_unset(struct peer *peer, afi_t afi, safi_t safi, + u_int32_t flag) { - return peer_af_flag_modify (peer, afi, safi, flag, 0); + return peer_af_flag_modify(peer, afi, safi, flag, 0); } -int peer_tx_shutdown_message_set (struct peer *peer, const char *msg) +int peer_tx_shutdown_message_set(struct peer *peer, const char *msg) { - XFREE (MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message); - peer->tx_shutdown_message = msg ? XSTRDUP (MTYPE_PEER_TX_SHUTDOWN_MSG, msg) : NULL; - return 0; + XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message); + peer->tx_shutdown_message = + msg ? XSTRDUP(MTYPE_PEER_TX_SHUTDOWN_MSG, msg) : NULL; + return 0; } -int peer_tx_shutdown_message_unset (struct peer *peer) +int peer_tx_shutdown_message_unset(struct peer *peer) { - XFREE (MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message); - return 0; + XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message); + return 0; } /* EBGP multihop configuration. */ -int -peer_ebgp_multihop_set (struct peer *peer, int ttl) -{ - struct peer_group *group; - struct listnode *node, *nnode; - struct peer *peer1; - - if (peer->sort == BGP_PEER_IBGP || peer->conf_if) - return 0; - - /* see comment in peer_ttl_security_hops_set() */ - if (ttl != MAXTTL) - { - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - group = peer->group; - if (group->conf->gtsm_hops != 0) - return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; - - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1)) - { - if (peer1->sort == BGP_PEER_IBGP) - continue; - - if (peer1->gtsm_hops != 0) - return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; - } - } - else - { - if (peer->gtsm_hops != 0) - return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; - } - } - - peer->ttl = ttl; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else - bgp_session_reset(peer); - } - } - else - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (peer->sort == BGP_PEER_IBGP) - continue; - - peer->ttl = group->conf->ttl; - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else - bgp_session_reset(peer); - } - } - return 0; -} - -int -peer_ebgp_multihop_unset (struct peer *peer) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - if (peer->sort == BGP_PEER_IBGP) - return 0; - - if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL) - return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; - - if (peer_group_active (peer)) - peer->ttl = peer->group->conf->ttl; - else - peer->ttl = 1; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else - bgp_session_reset(peer); - } - else - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (peer->sort == BGP_PEER_IBGP) - continue; +int peer_ebgp_multihop_set(struct peer *peer, int ttl) +{ + struct peer_group *group; + struct listnode *node, *nnode; + struct peer *peer1; + + if (peer->sort == BGP_PEER_IBGP || peer->conf_if) + return 0; + + /* see comment in peer_ttl_security_hops_set() */ + if (ttl != MAXTTL) { + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + group = peer->group; + if (group->conf->gtsm_hops != 0) + return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; + + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, + peer1)) { + if (peer1->sort == BGP_PEER_IBGP) + continue; + + if (peer1->gtsm_hops != 0) + return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; + } + } else { + if (peer->gtsm_hops != 0) + return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; + } + } - peer->ttl = 1; + peer->ttl = ttl; - if (peer->fd >= 0) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else - bgp_session_reset(peer); - } + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + bgp_session_reset(peer); + } + } else { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (peer->sort == BGP_PEER_IBGP) + continue; + + peer->ttl = group->conf->ttl; + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + bgp_session_reset(peer); + } } - } - return 0; + return 0; +} + +int peer_ebgp_multihop_unset(struct peer *peer) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + if (peer->sort == BGP_PEER_IBGP) + return 0; + + if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL) + return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; + + if (peer_group_active(peer)) + peer->ttl = peer->group->conf->ttl; + else + peer->ttl = 1; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + bgp_session_reset(peer); + } else { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (peer->sort == BGP_PEER_IBGP) + continue; + + peer->ttl = 1; + + if (peer->fd >= 0) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send( + peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + bgp_session_reset(peer); + } + } + } + return 0; } /* Neighbor description. */ -int -peer_description_set (struct peer *peer, const char *desc) +int peer_description_set(struct peer *peer, const char *desc) { - if (peer->desc) - XFREE (MTYPE_PEER_DESC, peer->desc); + if (peer->desc) + XFREE(MTYPE_PEER_DESC, peer->desc); - peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc); + peer->desc = XSTRDUP(MTYPE_PEER_DESC, desc); - return 0; + return 0; } -int -peer_description_unset (struct peer *peer) +int peer_description_unset(struct peer *peer) { - if (peer->desc) - XFREE (MTYPE_PEER_DESC, peer->desc); + if (peer->desc) + XFREE(MTYPE_PEER_DESC, peer->desc); - peer->desc = NULL; + peer->desc = NULL; - return 0; + return 0; } /* Neighbor update-source. */ -int -peer_update_source_if_set (struct peer *peer, const char *ifname) +int peer_update_source_if_set(struct peer *peer, const char *ifname) { - struct peer_group *group; - struct listnode *node, *nnode; + struct peer_group *group; + struct listnode *node, *nnode; - if (peer->update_if) - { - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP) - && strcmp (peer->update_if, ifname) == 0) - return 0; + if (peer->update_if) { + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) + && strcmp(peer->update_if, ifname) == 0) + return 0; - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; - } - - if (peer->update_source) - { - sockunion_free (peer->update_source); - peer->update_source = NULL; - } - - peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - return 0; - } - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (peer->update_if) - { - if (strcmp (peer->update_if, ifname) == 0) - continue; + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; + } - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; + if (peer->update_source) { + sockunion_free(peer->update_source); + peer->update_source = NULL; } - if (peer->update_source) - { - sockunion_free (peer->update_source); - peer->update_source = NULL; + peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + return 0; } - peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname); + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (peer->update_if) { + if (strcmp(peer->update_if, ifname) == 0) + continue; + + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; + } + + if (peer->update_source) { + sockunion_free(peer->update_source); + peer->update_source = NULL; + } + + peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname); - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - } - return 0; + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + } + return 0; } -int -peer_update_source_addr_set (struct peer *peer, const union sockunion *su) +int peer_update_source_addr_set(struct peer *peer, const union sockunion *su) { - struct peer_group *group; - struct listnode *node, *nnode; + struct peer_group *group; + struct listnode *node, *nnode; - if (peer->update_source) - { - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP) - && sockunion_cmp (peer->update_source, su) == 0) - return 0; - sockunion_free (peer->update_source); - peer->update_source = NULL; - } - - if (peer->update_if) - { - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; - - } - - peer->update_source = sockunion_dup (su); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - return 0; - } - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (peer->update_source) - { - if (sockunion_cmp (peer->update_source, su) == 0) - continue; - sockunion_free (peer->update_source); - peer->update_source = NULL; + if (peer->update_source) { + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) + && sockunion_cmp(peer->update_source, su) == 0) + return 0; + sockunion_free(peer->update_source); + peer->update_source = NULL; } - if (peer->update_if) - { - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; - } - - peer->update_source = sockunion_dup (su); - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - } - return 0; -} - -int -peer_update_source_unset (struct peer *peer) -{ - union sockunion *su; - struct peer_group *group; - struct listnode *node, *nnode; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP) - && ! peer->update_source - && ! peer->update_if) - return 0; - - if (peer->update_source) - { - sockunion_free (peer->update_source); - peer->update_source = NULL; - } - if (peer->update_if) - { - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; - } - - if (peer_group_active (peer)) - { - group = peer->group; - - if (group->conf->update_source) - { - su = sockunion_dup (group->conf->update_source); - peer->update_source = su; - } - else if (group->conf->update_if) - peer->update_if = - XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if); - } - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - return 0; - } - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (! peer->update_source && ! peer->update_if) - continue; - - if (peer->update_source) - { - sockunion_free (peer->update_source); - peer->update_source = NULL; + if (peer->update_if) { + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; } - if (peer->update_if) - { - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; + peer->update_source = sockunion_dup(su); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + return 0; } - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - } - return 0; + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (peer->update_source) { + if (sockunion_cmp(peer->update_source, su) == 0) + continue; + sockunion_free(peer->update_source); + peer->update_source = NULL; + } + + if (peer->update_if) { + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; + } + + peer->update_source = sockunion_dup(su); + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + } + return 0; } -int -peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi, - const char *rmap) +int peer_update_source_unset(struct peer *peer) { - struct peer_group *group; - struct listnode *node, *nnode; + union sockunion *su; + struct peer_group *group; + struct listnode *node, *nnode; - if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE) - || (rmap && ! peer->default_rmap[afi][safi].name) - || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0)) - { - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE); + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) && !peer->update_source + && !peer->update_if) + return 0; - if (rmap) - { - if (peer->default_rmap[afi][safi].name) - XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name); - peer->default_rmap[afi][safi].name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap); - } - } - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (peer->status == Established && peer->afc_nego[afi][safi]) { - update_group_adjust_peer(peer_af_find(peer, afi, safi)); - bgp_default_originate (peer, afi, safi, 0); - bgp_announce_route (peer, afi, safi); - } - return 0; - } - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE); - - if (rmap) - { - if (peer->default_rmap[afi][safi].name) - XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name); - peer->default_rmap[afi][safi].name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap); + if (peer->update_source) { + sockunion_free(peer->update_source); + peer->update_source = NULL; + } + if (peer->update_if) { + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; + } + + if (peer_group_active(peer)) { + group = peer->group; + + if (group->conf->update_source) { + su = sockunion_dup(group->conf->update_source); + peer->update_source = su; + } else if (group->conf->update_if) + peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, + group->conf->update_if); + } + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + return 0; } - if (peer->status == Established && peer->afc_nego[afi][safi]) { - update_group_adjust_peer(peer_af_find(peer, afi, safi)); - bgp_default_originate (peer, afi, safi, 0); - bgp_announce_route (peer, afi, safi); - } - } - return 0; + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (!peer->update_source && !peer->update_if) + continue; + + if (peer->update_source) { + sockunion_free(peer->update_source); + peer->update_source = NULL; + } + + if (peer->update_if) { + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; + } + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + } + return 0; } -int -peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi) +int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi, + const char *rmap) { - struct peer_group *group; - struct listnode *node, *nnode; + struct peer_group *group; + struct listnode *node, *nnode; - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)) - { - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE); + if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE) + || (rmap && !peer->default_rmap[afi][safi].name) + || (rmap + && strcmp(rmap, peer->default_rmap[afi][safi].name) != 0)) { + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_DEFAULT_ORIGINATE); - if (peer->default_rmap[afi][safi].name) - XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name); - peer->default_rmap[afi][safi].name = NULL; - peer->default_rmap[afi][safi].map = NULL; - } + if (rmap) { + if (peer->default_rmap[afi][safi].name) + XFREE(MTYPE_ROUTE_MAP_NAME, + peer->default_rmap[afi][safi].name); + peer->default_rmap[afi][safi].name = + XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); + peer->default_rmap[afi][safi].map = + route_map_lookup_by_name(rmap); + } + } - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (peer->status == Established && peer->afc_nego[afi][safi]) { - update_group_adjust_peer(peer_af_find(peer, afi, safi)); - bgp_default_originate (peer, afi, safi, 1); - bgp_announce_route (peer, afi, safi); - } - return 0; - } + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (peer->status == Established && peer->afc_nego[afi][safi]) { + update_group_adjust_peer(peer_af_find(peer, afi, safi)); + bgp_default_originate(peer, afi, safi, 0); + bgp_announce_route(peer, afi, safi); + } + return 0; + } - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE); + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_DEFAULT_ORIGINATE); + + if (rmap) { + if (peer->default_rmap[afi][safi].name) + XFREE(MTYPE_ROUTE_MAP_NAME, + peer->default_rmap[afi][safi].name); + peer->default_rmap[afi][safi].name = + XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); + peer->default_rmap[afi][safi].map = + route_map_lookup_by_name(rmap); + } - if (peer->default_rmap[afi][safi].name) - XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name); - peer->default_rmap[afi][safi].name = NULL; - peer->default_rmap[afi][safi].map = NULL; + if (peer->status == Established && peer->afc_nego[afi][safi]) { + update_group_adjust_peer(peer_af_find(peer, afi, safi)); + bgp_default_originate(peer, afi, safi, 0); + bgp_announce_route(peer, afi, safi); + } + } + return 0; +} - if (peer->status == Established && peer->afc_nego[afi][safi]) { - update_group_adjust_peer(peer_af_find(peer, afi, safi)); - bgp_default_originate (peer, afi, safi, 1); - bgp_announce_route (peer, afi, safi); - } - } - return 0; +int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_DEFAULT_ORIGINATE)) { + UNSET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_DEFAULT_ORIGINATE); + + if (peer->default_rmap[afi][safi].name) + XFREE(MTYPE_ROUTE_MAP_NAME, + peer->default_rmap[afi][safi].name); + peer->default_rmap[afi][safi].name = NULL; + peer->default_rmap[afi][safi].map = NULL; + } + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (peer->status == Established && peer->afc_nego[afi][safi]) { + update_group_adjust_peer(peer_af_find(peer, afi, safi)); + bgp_default_originate(peer, afi, safi, 1); + bgp_announce_route(peer, afi, safi); + } + return 0; + } + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + UNSET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_DEFAULT_ORIGINATE); + + if (peer->default_rmap[afi][safi].name) + XFREE(MTYPE_ROUTE_MAP_NAME, + peer->default_rmap[afi][safi].name); + peer->default_rmap[afi][safi].name = NULL; + peer->default_rmap[afi][safi].map = NULL; + + if (peer->status == Established && peer->afc_nego[afi][safi]) { + update_group_adjust_peer(peer_af_find(peer, afi, safi)); + bgp_default_originate(peer, afi, safi, 1); + bgp_announce_route(peer, afi, safi); + } + } + return 0; } -int -peer_port_set (struct peer *peer, u_int16_t port) +int peer_port_set(struct peer *peer, u_int16_t port) { - peer->port = port; - return 0; + peer->port = port; + return 0; } -int -peer_port_unset (struct peer *peer) +int peer_port_unset(struct peer *peer) { - peer->port = BGP_PORT_DEFAULT; - return 0; + peer->port = BGP_PORT_DEFAULT; + return 0; } /* @@ -4682,1605 +4382,1579 @@ peer_port_unset (struct peer *peer) * being used by a peer has changed (AF specific). Automatically * initiates inbound or outbound processing as needed. */ -static void -peer_on_policy_change (struct peer *peer, afi_t afi, safi_t safi, int outbound) +static void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi, + int outbound) +{ + if (outbound) { + update_group_adjust_peer(peer_af_find(peer, afi, safi)); + if (peer->status == Established) + bgp_announce_route(peer, afi, safi); + } else { + if (peer->status != Established) + return; + + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SOFT_RECONFIG)) + bgp_soft_reconfig_in(peer, afi, safi); + else if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV) + || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV)) + bgp_route_refresh_send(peer, afi, safi, 0, 0, 0); + } +} + + +/* neighbor weight. */ +int peer_weight_set(struct peer *peer, afi_t afi, safi_t safi, u_int16_t weight) { - if (outbound) - { - update_group_adjust_peer (peer_af_find (peer, afi, safi)); - if (peer->status == Established) - bgp_announce_route(peer, afi, safi); - } - else - { - if (peer->status != Established) - return; + struct peer_group *group; + struct listnode *node, *nnode; - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) - bgp_soft_reconfig_in (peer, afi, safi); - else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV) - || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV)) - bgp_route_refresh_send (peer, afi, safi, 0, 0, 0); - } + if (peer->weight[afi][safi] != weight) { + peer->weight[afi][safi] = weight; + SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT); + peer_on_policy_change(peer, afi, safi, 0); + } + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (peer->weight[afi][safi] != weight) { + peer->weight[afi][safi] = weight; + SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT); + peer_on_policy_change(peer, afi, safi, 0); + } + } + return 0; } +int peer_weight_unset(struct peer *peer, afi_t afi, safi_t safi) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + /* not the peer-group itself but a peer in a peer-group */ + if (peer_group_active(peer)) { + group = peer->group; + + /* inherit weight from the peer-group */ + if (CHECK_FLAG(group->conf->af_flags[afi][safi], + PEER_FLAG_WEIGHT)) { + peer->weight[afi][safi] = + group->conf->weight[afi][safi]; + peer_af_flag_set(peer, afi, safi, PEER_FLAG_WEIGHT); + peer_on_policy_change(peer, afi, safi, 0); + } else { + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_WEIGHT)) { + peer->weight[afi][safi] = 0; + peer_af_flag_unset(peer, afi, safi, + PEER_FLAG_WEIGHT); + peer_on_policy_change(peer, afi, safi, 0); + } + } + } + + else { + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT)) { + peer->weight[afi][safi] = 0; + peer_af_flag_unset(peer, afi, safi, PEER_FLAG_WEIGHT); + peer_on_policy_change(peer, afi, safi, 0); + } -/* neighbor weight. */ -int -peer_weight_set (struct peer *peer, afi_t afi, safi_t safi, u_int16_t weight) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - if (peer->weight[afi][safi] != weight) - { - peer->weight[afi][safi] = weight; - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT); - peer_on_policy_change (peer, afi, safi, 0); - } - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (peer->weight[afi][safi] != weight) - { - peer->weight[afi][safi] = weight; - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT); - peer_on_policy_change (peer, afi, safi, 0); - } - } - return 0; -} - -int -peer_weight_unset (struct peer *peer, afi_t afi, safi_t safi) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - /* not the peer-group itself but a peer in a peer-group */ - if (peer_group_active (peer)) - { - group = peer->group; - - /* inherit weight from the peer-group */ - if (CHECK_FLAG (group->conf->af_flags[afi][safi], PEER_FLAG_WEIGHT)) - { - peer->weight[afi][safi] = group->conf->weight[afi][safi]; - peer_af_flag_set (peer, afi, safi, PEER_FLAG_WEIGHT); - peer_on_policy_change (peer, afi, safi, 0); - } - else - { - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT)) - { - peer->weight[afi][safi] = 0; - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_WEIGHT); - peer_on_policy_change (peer, afi, safi, 0); - } - } - } - - else - { - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT)) - { - peer->weight[afi][safi] = 0; - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_WEIGHT); - peer_on_policy_change (peer, afi, safi, 0); - } - - /* peer-group member updates. */ - group = peer->group; - - if (group) - { - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT)) - { - peer->weight[afi][safi] = 0; - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_WEIGHT); - peer_on_policy_change (peer, afi, safi, 0); - } - } - } - } - return 0; -} - -int -peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - /* keepalive value check. */ - if (keepalive > 65535) - return BGP_ERR_INVALID_VALUE; - - /* Holdtime value check. */ - if (holdtime > 65535) - return BGP_ERR_INVALID_VALUE; - - /* Holdtime value must be either 0 or greater than 3. */ - if (holdtime < 3 && holdtime != 0) - return BGP_ERR_INVALID_VALUE; - - /* Set value to the configuration. */ - SET_FLAG (peer->config, PEER_CONFIG_TIMER); - peer->holdtime = holdtime; - peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - SET_FLAG (peer->config, PEER_CONFIG_TIMER); - peer->holdtime = group->conf->holdtime; - peer->keepalive = group->conf->keepalive; - } - return 0; -} - -int -peer_timers_unset (struct peer *peer) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - /* Clear configuration. */ - UNSET_FLAG (peer->config, PEER_CONFIG_TIMER); - peer->keepalive = 0; - peer->holdtime = 0; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - UNSET_FLAG (peer->config, PEER_CONFIG_TIMER); - peer->holdtime = 0; - peer->keepalive = 0; - } - - return 0; -} - -int -peer_timers_connect_set (struct peer *peer, u_int32_t connect) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - if (connect > 65535) - return BGP_ERR_INVALID_VALUE; - - /* Set value to the configuration. */ - SET_FLAG (peer->config, PEER_CONFIG_CONNECT); - peer->connect = connect; - - /* Set value to timer setting. */ - peer->v_connect = connect; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - SET_FLAG (peer->config, PEER_CONFIG_CONNECT); - peer->connect = connect; - peer->v_connect = connect; - } - return 0; -} - -int -peer_timers_connect_unset (struct peer *peer) + /* peer-group member updates. */ + group = peer->group; + + if (group) { + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, + peer)) { + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_WEIGHT)) { + peer->weight[afi][safi] = 0; + peer_af_flag_unset(peer, afi, safi, + PEER_FLAG_WEIGHT); + peer_on_policy_change(peer, afi, safi, + 0); + } + } + } + } + return 0; +} + +int peer_timers_set(struct peer *peer, u_int32_t keepalive, u_int32_t holdtime) { - struct peer_group *group; - struct listnode *node, *nnode; + struct peer_group *group; + struct listnode *node, *nnode; + + /* keepalive value check. */ + if (keepalive > 65535) + return BGP_ERR_INVALID_VALUE; - /* Clear configuration. */ - UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT); - peer->connect = 0; + /* Holdtime value check. */ + if (holdtime > 65535) + return BGP_ERR_INVALID_VALUE; - /* Set timer setting to default value. */ - peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; + /* Holdtime value must be either 0 or greater than 3. */ + if (holdtime < 3 && holdtime != 0) + return BGP_ERR_INVALID_VALUE; - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT); - peer->connect = 0; - peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; - } - return 0; -} - -int -peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv) + /* Set value to the configuration. */ + SET_FLAG(peer->config, PEER_CONFIG_TIMER); + peer->holdtime = holdtime; + peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + SET_FLAG(peer->config, PEER_CONFIG_TIMER); + peer->holdtime = group->conf->holdtime; + peer->keepalive = group->conf->keepalive; + } + return 0; +} + +int peer_timers_unset(struct peer *peer) { - struct peer_group *group; - struct listnode *node, *nnode; + struct peer_group *group; + struct listnode *node, *nnode; - if (routeadv > 600) - return BGP_ERR_INVALID_VALUE; - - SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV); - peer->routeadv = routeadv; - peer->v_routeadv = routeadv; + /* Clear configuration. */ + UNSET_FLAG(peer->config, PEER_CONFIG_TIMER); + peer->keepalive = 0; + peer->holdtime = 0; - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) { - update_group_adjust_peer_afs (peer); - if (peer->status == Established) - bgp_announce_route_all (peer); - return 0; - } + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + UNSET_FLAG(peer->config, PEER_CONFIG_TIMER); + peer->holdtime = 0; + peer->keepalive = 0; + } - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV); - peer->routeadv = routeadv; - peer->v_routeadv = routeadv; - update_group_adjust_peer_afs (peer); - if (peer->status == Established) - bgp_announce_route_all (peer); - } - - return 0; + return 0; +} + +int peer_timers_connect_set(struct peer *peer, u_int32_t connect) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + if (connect > 65535) + return BGP_ERR_INVALID_VALUE; + + /* Set value to the configuration. */ + SET_FLAG(peer->config, PEER_CONFIG_CONNECT); + peer->connect = connect; + + /* Set value to timer setting. */ + peer->v_connect = connect; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + SET_FLAG(peer->config, PEER_CONFIG_CONNECT); + peer->connect = connect; + peer->v_connect = connect; + } + return 0; +} + +int peer_timers_connect_unset(struct peer *peer) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + /* Clear configuration. */ + UNSET_FLAG(peer->config, PEER_CONFIG_CONNECT); + peer->connect = 0; + + /* Set timer setting to default value. */ + peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + UNSET_FLAG(peer->config, PEER_CONFIG_CONNECT); + peer->connect = 0; + peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; + } + return 0; } -int -peer_advertise_interval_unset (struct peer *peer) +int peer_advertise_interval_set(struct peer *peer, u_int32_t routeadv) { - struct peer_group *group; - struct listnode *node, *nnode; + struct peer_group *group; + struct listnode *node, *nnode; + + if (routeadv > 600) + return BGP_ERR_INVALID_VALUE; + + SET_FLAG(peer->config, PEER_CONFIG_ROUTEADV); + peer->routeadv = routeadv; + peer->v_routeadv = routeadv; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + update_group_adjust_peer_afs(peer); + if (peer->status == Established) + bgp_announce_route_all(peer); + return 0; + } + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + SET_FLAG(peer->config, PEER_CONFIG_ROUTEADV); + peer->routeadv = routeadv; + peer->v_routeadv = routeadv; + update_group_adjust_peer_afs(peer); + if (peer->status == Established) + bgp_announce_route_all(peer); + } + + return 0; +} + +int peer_advertise_interval_unset(struct peer *peer) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + UNSET_FLAG(peer->config, PEER_CONFIG_ROUTEADV); + peer->routeadv = 0; + + if (peer->sort == BGP_PEER_IBGP) + peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; + else + peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + update_group_adjust_peer_afs(peer); + if (peer->status == Established) + bgp_announce_route_all(peer); + return 0; + } + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + UNSET_FLAG(peer->config, PEER_CONFIG_ROUTEADV); + peer->routeadv = 0; + + if (peer->sort == BGP_PEER_IBGP) + peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; + else + peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; + + update_group_adjust_peer_afs(peer); + if (peer->status == Established) + bgp_announce_route_all(peer); + } - UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV); - peer->routeadv = 0; - - if (peer->sort == BGP_PEER_IBGP) - peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; - else - peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) { - update_group_adjust_peer_afs (peer); - if (peer->status == Established) - bgp_announce_route_all (peer); - return 0; - } - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV); - peer->routeadv = 0; - - if (peer->sort == BGP_PEER_IBGP) - peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; - else - peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; - - update_group_adjust_peer_afs (peer); - if (peer->status == Established) - bgp_announce_route_all (peer); - } - - return 0; + return 0; } /* neighbor interface */ -void -peer_interface_set (struct peer *peer, const char *str) +void peer_interface_set(struct peer *peer, const char *str) { - if (peer->ifname) - XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname); - peer->ifname = XSTRDUP(MTYPE_BGP_PEER_IFNAME, str); + if (peer->ifname) + XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname); + peer->ifname = XSTRDUP(MTYPE_BGP_PEER_IFNAME, str); } -void -peer_interface_unset (struct peer *peer) +void peer_interface_unset(struct peer *peer) { - if (peer->ifname) - XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname); - peer->ifname = NULL; + if (peer->ifname) + XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname); + peer->ifname = NULL; } /* Allow-as in. */ -int -peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num, - int origin) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - if (origin) - { - if (peer->allowas_in[afi][safi] || - CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) || - !CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) - { - peer->allowas_in[afi][safi] = 0; - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN); - peer_af_flag_set (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); - peer_on_policy_change (peer, afi, safi, 0); - } - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (peer->allowas_in[afi][safi] || - CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) || - !CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) - { - peer->allowas_in[afi][safi] = 0; - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN); - peer_af_flag_set (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); - peer_on_policy_change (peer, afi, safi, 0); - } - } - } - else - { - if (allow_num < 1 || allow_num > 10) - return BGP_ERR_INVALID_VALUE; - - if (peer->allowas_in[afi][safi] != allow_num || - CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) - { - peer->allowas_in[afi][safi] = allow_num; - peer_af_flag_set (peer, afi, safi, PEER_FLAG_ALLOWAS_IN); - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); - peer_on_policy_change (peer, afi, safi, 0); - } - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (peer->allowas_in[afi][safi] != allow_num || - CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) - { - peer->allowas_in[afi][safi] = allow_num; - peer_af_flag_set (peer, afi, safi, PEER_FLAG_ALLOWAS_IN); - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); - peer_on_policy_change (peer, afi, safi, 0); - } - } - } - - return 0; -} - -int -peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi) -{ - struct peer_group *group; - struct peer *tmp_peer; - struct listnode *node, *nnode; - - /* If this is a peer-group we must first clear the flags for all of the - * peer-group members - */ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer)) - { - if (CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) || - CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) - { - tmp_peer->allowas_in[afi][safi] = 0; - peer_af_flag_unset (tmp_peer, afi, safi, PEER_FLAG_ALLOWAS_IN); - peer_af_flag_unset (tmp_peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); - peer_on_policy_change (tmp_peer, afi, safi, 0); - } - } - } - - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) || - CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) - { - peer->allowas_in[afi][safi] = 0; - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN); - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); - peer_on_policy_change (peer, afi, safi, 0); - } - - return 0; -} - -int -peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as) -{ - struct bgp *bgp = peer->bgp; - struct peer_group *group; - struct listnode *node, *nnode; - - if (peer_sort (peer) != BGP_PEER_EBGP - && peer_sort (peer) != BGP_PEER_INTERNAL) - return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP; - - if (bgp->as == as) - return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS; - - if (peer->as == as) - return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS; - - if (peer->change_local_as == as && - ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend) - || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) && - ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as) - || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as))) - return 0; - - peer->change_local_as = as; - if (no_prepend) - SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); - else - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); - - if (replace_as) - SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); - else - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - peer->change_local_as = as; - if (no_prepend) - SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); - else - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); - - if (replace_as) - SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); - else - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - BGP_EVENT_ADD (peer, BGP_Stop); - } - - return 0; -} - -int -peer_local_as_unset (struct peer *peer) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - if (! peer->change_local_as) - return 0; - - peer->change_local_as = 0; - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - BGP_EVENT_ADD (peer, BGP_Stop); - - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - peer->change_local_as = 0; - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - } - return 0; +int peer_allowas_in_set(struct peer *peer, afi_t afi, safi_t safi, + int allow_num, int origin) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + if (origin) { + if (peer->allowas_in[afi][safi] + || CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN) + || !CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN_ORIGIN)) { + peer->allowas_in[afi][safi] = 0; + peer_af_flag_unset(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN); + peer_af_flag_set(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN_ORIGIN); + peer_on_policy_change(peer, afi, safi, 0); + } + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (peer->allowas_in[afi][safi] + || CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN) + || !CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN_ORIGIN)) { + peer->allowas_in[afi][safi] = 0; + peer_af_flag_unset(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN); + peer_af_flag_set(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN_ORIGIN); + peer_on_policy_change(peer, afi, safi, 0); + } + } + } else { + if (allow_num < 1 || allow_num > 10) + return BGP_ERR_INVALID_VALUE; + + if (peer->allowas_in[afi][safi] != allow_num + || CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN_ORIGIN)) { + peer->allowas_in[afi][safi] = allow_num; + peer_af_flag_set(peer, afi, safi, PEER_FLAG_ALLOWAS_IN); + peer_af_flag_unset(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN_ORIGIN); + peer_on_policy_change(peer, afi, safi, 0); + } + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (peer->allowas_in[afi][safi] != allow_num + || CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN_ORIGIN)) { + peer->allowas_in[afi][safi] = allow_num; + peer_af_flag_set(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN); + peer_af_flag_unset(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN_ORIGIN); + peer_on_policy_change(peer, afi, safi, 0); + } + } + } + + return 0; +} + +int peer_allowas_in_unset(struct peer *peer, afi_t afi, safi_t safi) +{ + struct peer_group *group; + struct peer *tmp_peer; + struct listnode *node, *nnode; + + /* If this is a peer-group we must first clear the flags for all of the + * peer-group members + */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) { + if (CHECK_FLAG(tmp_peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN) + || CHECK_FLAG(tmp_peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN_ORIGIN)) { + tmp_peer->allowas_in[afi][safi] = 0; + peer_af_flag_unset(tmp_peer, afi, safi, + PEER_FLAG_ALLOWAS_IN); + peer_af_flag_unset(tmp_peer, afi, safi, + PEER_FLAG_ALLOWAS_IN_ORIGIN); + peer_on_policy_change(tmp_peer, afi, safi, 0); + } + } + } + + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) + || CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN_ORIGIN)) { + peer->allowas_in[afi][safi] = 0; + peer_af_flag_unset(peer, afi, safi, PEER_FLAG_ALLOWAS_IN); + peer_af_flag_unset(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN_ORIGIN); + peer_on_policy_change(peer, afi, safi, 0); + } + + return 0; +} + +int peer_local_as_set(struct peer *peer, as_t as, int no_prepend, + int replace_as) +{ + struct bgp *bgp = peer->bgp; + struct peer_group *group; + struct listnode *node, *nnode; + + if (peer_sort(peer) != BGP_PEER_EBGP + && peer_sort(peer) != BGP_PEER_INTERNAL) + return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP; + + if (bgp->as == as) + return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS; + + if (peer->as == as) + return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS; + + if (peer->change_local_as == as + && ((CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) + && no_prepend) + || (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) + && !no_prepend)) + && ((CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) + && replace_as) + || (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) + && !replace_as))) + return 0; + + peer->change_local_as = as; + if (no_prepend) + SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); + else + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); + + if (replace_as) + SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); + else + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + peer->change_local_as = as; + if (no_prepend) + SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); + else + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); + + if (replace_as) + SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); + else + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + BGP_EVENT_ADD(peer, BGP_Stop); + } + + return 0; +} + +int peer_local_as_unset(struct peer *peer) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + if (!peer->change_local_as) + return 0; + + peer->change_local_as = 0; + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + BGP_EVENT_ADD(peer, BGP_Stop); + + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + peer->change_local_as = 0; + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + } + return 0; } /* Set password for authenticating with the peer. */ -int -peer_password_set (struct peer *peer, const char *password) -{ - struct listnode *nn, *nnode; - int len = password ? strlen(password) : 0; - int ret = BGP_SUCCESS; - - if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN)) - return BGP_ERR_INVALID_VALUE; - - if (peer->password && strcmp (peer->password, password) == 0 - && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - if (peer->password) - XFREE (MTYPE_PEER_PASSWORD, peer->password); - - peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else - bgp_session_reset(peer); - - if (BGP_PEER_SU_UNSPEC(peer)) - return BGP_SUCCESS; - - return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED; - } - - for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer)) - { - if (peer->password && strcmp (peer->password, password) == 0) - continue; - - if (peer->password) - XFREE (MTYPE_PEER_PASSWORD, peer->password); - - peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password); - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else - bgp_session_reset(peer); - - if (! BGP_PEER_SU_UNSPEC(peer)) - { - if (bgp_md5_set (peer) < 0) - ret = BGP_ERR_TCPSIG_FAILED; - } - } - - return ret; -} - -int -peer_password_unset (struct peer *peer) -{ - struct listnode *nn, *nnode; - - if (!peer->password - && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else - bgp_session_reset(peer); - - if (peer->password) - XFREE (MTYPE_PEER_PASSWORD, peer->password); - - peer->password = NULL; - - if (! BGP_PEER_SU_UNSPEC(peer)) - bgp_md5_unset (peer); - - return 0; - } - - XFREE (MTYPE_PEER_PASSWORD, peer->password); - peer->password = NULL; - - for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer)) - { - if (!peer->password) - continue; - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else - bgp_session_reset(peer); - - XFREE (MTYPE_PEER_PASSWORD, peer->password); - peer->password = NULL; - - if (! BGP_PEER_SU_UNSPEC(peer)) - bgp_md5_unset (peer); - } - - return 0; +int peer_password_set(struct peer *peer, const char *password) +{ + struct listnode *nn, *nnode; + int len = password ? strlen(password) : 0; + int ret = BGP_SUCCESS; + + if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN)) + return BGP_ERR_INVALID_VALUE; + + if (peer->password && strcmp(peer->password, password) == 0 + && !CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + if (peer->password) + XFREE(MTYPE_PEER_PASSWORD, peer->password); + + peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + bgp_session_reset(peer); + + if (BGP_PEER_SU_UNSPEC(peer)) + return BGP_SUCCESS; + + return (bgp_md5_set(peer) >= 0) ? BGP_SUCCESS + : BGP_ERR_TCPSIG_FAILED; + } + + for (ALL_LIST_ELEMENTS(peer->group->peer, nn, nnode, peer)) { + if (peer->password && strcmp(peer->password, password) == 0) + continue; + + if (peer->password) + XFREE(MTYPE_PEER_PASSWORD, peer->password); + + peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password); + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + bgp_session_reset(peer); + + if (!BGP_PEER_SU_UNSPEC(peer)) { + if (bgp_md5_set(peer) < 0) + ret = BGP_ERR_TCPSIG_FAILED; + } + } + + return ret; +} + +int peer_password_unset(struct peer *peer) +{ + struct listnode *nn, *nnode; + + if (!peer->password && !CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + bgp_session_reset(peer); + + if (peer->password) + XFREE(MTYPE_PEER_PASSWORD, peer->password); + + peer->password = NULL; + + if (!BGP_PEER_SU_UNSPEC(peer)) + bgp_md5_unset(peer); + + return 0; + } + + XFREE(MTYPE_PEER_PASSWORD, peer->password); + peer->password = NULL; + + for (ALL_LIST_ELEMENTS(peer->group->peer, nn, nnode, peer)) { + if (!peer->password) + continue; + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + bgp_session_reset(peer); + + XFREE(MTYPE_PEER_PASSWORD, peer->password); + peer->password = NULL; + + if (!BGP_PEER_SU_UNSPEC(peer)) + bgp_md5_unset(peer); + } + + return 0; } /* Set distribute list to the peer. */ -int -peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct, - const char *name) +int peer_distribute_set(struct peer *peer, afi_t afi, safi_t safi, int direct, + const char *name) { - struct bgp_filter *filter; - struct peer_group *group; - struct listnode *node, *nnode; + struct bgp_filter *filter; + struct peer_group *group; + struct listnode *node, *nnode; - if (direct != FILTER_IN && direct != FILTER_OUT) - return BGP_ERR_INVALID_VALUE; + if (direct != FILTER_IN && direct != FILTER_OUT) + return BGP_ERR_INVALID_VALUE; - filter = &peer->filter[afi][safi]; + filter = &peer->filter[afi][safi]; - if (filter->plist[direct].name) - return BGP_ERR_PEER_FILTER_CONFLICT; + if (filter->plist[direct].name) + return BGP_ERR_PEER_FILTER_CONFLICT; - if (filter->dlist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name); - filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->dlist[direct].alist = access_list_lookup (afi, name); + if (filter->dlist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name); + filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->dlist[direct].alist = access_list_lookup(afi, name); - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + filter = &peer->filter[afi][safi]; - if (filter->dlist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name); - filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->dlist[direct].alist = access_list_lookup (afi, name); - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - } + if (filter->dlist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->dlist[direct].name); + filter->dlist[direct].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->dlist[direct].alist = access_list_lookup(afi, name); + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + } - return 0; + return 0; } -int -peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct) +int peer_distribute_unset(struct peer *peer, afi_t afi, safi_t safi, int direct) { - struct bgp_filter *filter; - struct bgp_filter *gfilter; - struct peer_group *group; - struct listnode *node, *nnode; + struct bgp_filter *filter; + struct bgp_filter *gfilter; + struct peer_group *group; + struct listnode *node, *nnode; - if (direct != FILTER_IN && direct != FILTER_OUT) - return BGP_ERR_INVALID_VALUE; + if (direct != FILTER_IN && direct != FILTER_OUT) + return BGP_ERR_INVALID_VALUE; - filter = &peer->filter[afi][safi]; + filter = &peer->filter[afi][safi]; - /* apply peer-group filter */ - if (peer_group_active(peer)) - { - gfilter = &peer->group->conf->filter[afi][safi]; + /* apply peer-group filter */ + if (peer_group_active(peer)) { + gfilter = &peer->group->conf->filter[afi][safi]; + + if (gfilter->dlist[direct].name) { + if (filter->dlist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->dlist[direct].name); + filter->dlist[direct].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, + gfilter->dlist[direct].name); + filter->dlist[direct].alist = + gfilter->dlist[direct].alist; + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } + } - if (gfilter->dlist[direct].name) - { - if (filter->dlist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name); - filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->dlist[direct].name); - filter->dlist[direct].alist = gfilter->dlist[direct].alist; - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } - } - - if (filter->dlist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name); - filter->dlist[direct].name = NULL; - filter->dlist[direct].alist = NULL; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; - - if (filter->dlist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name); - filter->dlist[direct].name = NULL; - filter->dlist[direct].alist = NULL; - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - } - - return 0; -} + if (filter->dlist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name); + filter->dlist[direct].name = NULL; + filter->dlist[direct].alist = NULL; -/* Update distribute list. */ -static void -peer_distribute_update (struct access_list *access) -{ - afi_t afi; - safi_t safi; - int direct; - struct listnode *mnode, *mnnode; - struct listnode *node, *nnode; - struct bgp *bgp; - struct peer *peer; - struct peer_group *group; - struct bgp_filter *filter; - - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) - { - if (access->name) - update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, access->name, - 0, 0); - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { filter = &peer->filter[afi][safi]; - for (direct = FILTER_IN; direct < FILTER_MAX; direct++) - { - if (filter->dlist[direct].name) - filter->dlist[direct].alist = - access_list_lookup (afi, filter->dlist[direct].name); - else - filter->dlist[direct].alist = NULL; - } - } - } - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - filter = &group->conf->filter[afi][safi]; - - for (direct = FILTER_IN; direct < FILTER_MAX; direct++) - { - if (filter->dlist[direct].name) - filter->dlist[direct].alist = - access_list_lookup (afi, filter->dlist[direct].name); - else - filter->dlist[direct].alist = NULL; - } - } + if (filter->dlist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->dlist[direct].name); + filter->dlist[direct].name = NULL; + filter->dlist[direct].alist = NULL; + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); } + + return 0; +} + +/* Update distribute list. */ +static void peer_distribute_update(struct access_list *access) +{ + afi_t afi; + safi_t safi; + int direct; + struct listnode *mnode, *mnnode; + struct listnode *node, *nnode; + struct bgp *bgp; + struct peer *peer; + struct peer_group *group; + struct bgp_filter *filter; + + for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) { + if (access->name) + update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, + access->name, 0, 0); + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; + safi++) { + filter = &peer->filter[afi][safi]; + + for (direct = FILTER_IN; + direct < FILTER_MAX; direct++) { + if (filter->dlist[direct].name) + filter->dlist[direct] + .alist = access_list_lookup( + afi, + filter->dlist[direct] + .name); + else + filter->dlist[direct] + .alist = NULL; + } + } + } + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; + safi++) { + filter = + &group->conf->filter[afi][safi]; + + for (direct = FILTER_IN; + direct < FILTER_MAX; direct++) { + if (filter->dlist[direct].name) + filter->dlist[direct] + .alist = access_list_lookup( + afi, + filter->dlist[direct] + .name); + else + filter->dlist[direct] + .alist = NULL; + } + } + } #if ENABLE_BGP_VNC - vnc_prefix_list_update(bgp); + vnc_prefix_list_update(bgp); #endif - } + } } /* Set prefix list to the peer. */ -int -peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct, - const char *name) +int peer_prefix_list_set(struct peer *peer, afi_t afi, safi_t safi, int direct, + const char *name) { - struct bgp_filter *filter; - struct peer_group *group; - struct listnode *node, *nnode; + struct bgp_filter *filter; + struct peer_group *group; + struct listnode *node, *nnode; - if (direct != FILTER_IN && direct != FILTER_OUT) - return BGP_ERR_INVALID_VALUE; + if (direct != FILTER_IN && direct != FILTER_OUT) + return BGP_ERR_INVALID_VALUE; - filter = &peer->filter[afi][safi]; + filter = &peer->filter[afi][safi]; - if (filter->dlist[direct].name) - return BGP_ERR_PEER_FILTER_CONFLICT; + if (filter->dlist[direct].name) + return BGP_ERR_PEER_FILTER_CONFLICT; - if (filter->plist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name); - filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->plist[direct].plist = prefix_list_lookup (afi, name); + if (filter->plist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name); + filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->plist[direct].plist = prefix_list_lookup(afi, name); - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + filter = &peer->filter[afi][safi]; - if (filter->plist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name); - filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->plist[direct].plist = prefix_list_lookup (afi, name); - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - } - return 0; + if (filter->plist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->plist[direct].name); + filter->plist[direct].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->plist[direct].plist = prefix_list_lookup(afi, name); + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + } + return 0; } -int -peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct) +int peer_prefix_list_unset(struct peer *peer, afi_t afi, safi_t safi, + int direct) { - struct bgp_filter *filter; - struct bgp_filter *gfilter; - struct peer_group *group; - struct listnode *node, *nnode; + struct bgp_filter *filter; + struct bgp_filter *gfilter; + struct peer_group *group; + struct listnode *node, *nnode; - if (direct != FILTER_IN && direct != FILTER_OUT) - return BGP_ERR_INVALID_VALUE; + if (direct != FILTER_IN && direct != FILTER_OUT) + return BGP_ERR_INVALID_VALUE; - filter = &peer->filter[afi][safi]; + filter = &peer->filter[afi][safi]; - /* apply peer-group filter */ - if (peer_group_active(peer)) - { - gfilter = &peer->group->conf->filter[afi][safi]; + /* apply peer-group filter */ + if (peer_group_active(peer)) { + gfilter = &peer->group->conf->filter[afi][safi]; + + if (gfilter->plist[direct].name) { + if (filter->plist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->plist[direct].name); + filter->plist[direct].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, + gfilter->plist[direct].name); + filter->plist[direct].plist = + gfilter->plist[direct].plist; + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } + } - if (gfilter->plist[direct].name) - { - if (filter->plist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name); - filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->plist[direct].name); - filter->plist[direct].plist = gfilter->plist[direct].plist; - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } - } - - if (filter->plist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name); - filter->plist[direct].name = NULL; - filter->plist[direct].plist = NULL; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; - - if (filter->plist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name); - filter->plist[direct].name = NULL; - filter->plist[direct].plist = NULL; - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - } - - return 0; + if (filter->plist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name); + filter->plist[direct].name = NULL; + filter->plist[direct].plist = NULL; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + filter = &peer->filter[afi][safi]; + + if (filter->plist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->plist[direct].name); + filter->plist[direct].name = NULL; + filter->plist[direct].plist = NULL; + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + } + + return 0; } /* Update prefix-list list. */ -static void -peer_prefix_list_update (struct prefix_list *plist) -{ - struct listnode *mnode, *mnnode; - struct listnode *node, *nnode; - struct bgp *bgp; - struct peer *peer; - struct peer_group *group; - struct bgp_filter *filter; - afi_t afi; - safi_t safi; - int direct; - - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) - { - - /* - * Update the prefix-list on update groups. - */ - update_group_policy_update(bgp, BGP_POLICY_PREFIX_LIST, - plist ? prefix_list_name(plist) : NULL, 0, 0); - - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { +static void peer_prefix_list_update(struct prefix_list *plist) +{ + struct listnode *mnode, *mnnode; + struct listnode *node, *nnode; + struct bgp *bgp; + struct peer *peer; + struct peer_group *group; + struct bgp_filter *filter; + afi_t afi; + safi_t safi; + int direct; + + for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) { + + /* + * Update the prefix-list on update groups. + */ + update_group_policy_update( + bgp, BGP_POLICY_PREFIX_LIST, + plist ? prefix_list_name(plist) : NULL, 0, 0); + + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; + safi++) { + filter = &peer->filter[afi][safi]; + + for (direct = FILTER_IN; + direct < FILTER_MAX; direct++) { + if (filter->plist[direct].name) + filter->plist[direct] + .plist = prefix_list_lookup( + afi, + filter->plist[direct] + .name); + else + filter->plist[direct] + .plist = NULL; + } + } + } + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; + safi++) { + filter = + &group->conf->filter[afi][safi]; + + for (direct = FILTER_IN; + direct < FILTER_MAX; direct++) { + if (filter->plist[direct].name) + filter->plist[direct] + .plist = prefix_list_lookup( + afi, + filter->plist[direct] + .name); + else + filter->plist[direct] + .plist = NULL; + } + } + } + } +} + +int peer_aslist_set(struct peer *peer, afi_t afi, safi_t safi, int direct, + const char *name) +{ + struct bgp_filter *filter; + struct peer_group *group; + struct listnode *node, *nnode; + + if (direct != FILTER_IN && direct != FILTER_OUT) + return BGP_ERR_INVALID_VALUE; + + filter = &peer->filter[afi][safi]; + + if (filter->aslist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name); + filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->aslist[direct].aslist = as_list_lookup(name); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { filter = &peer->filter[afi][safi]; - for (direct = FILTER_IN; direct < FILTER_MAX; direct++) - { - if (filter->plist[direct].name) - filter->plist[direct].plist = - prefix_list_lookup (afi, filter->plist[direct].name); - else - filter->plist[direct].plist = NULL; - } - } - } - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - filter = &group->conf->filter[afi][safi]; - - for (direct = FILTER_IN; direct < FILTER_MAX; direct++) - { - if (filter->plist[direct].name) - filter->plist[direct].plist = - prefix_list_lookup (afi, filter->plist[direct].name); - else - filter->plist[direct].plist = NULL; - } - } - } - } -} - -int -peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct, - const char *name) -{ - struct bgp_filter *filter; - struct peer_group *group; - struct listnode *node, *nnode; - - if (direct != FILTER_IN && direct != FILTER_OUT) - return BGP_ERR_INVALID_VALUE; - - filter = &peer->filter[afi][safi]; - - if (filter->aslist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name); - filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->aslist[direct].aslist = as_list_lookup (name); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; - - if (filter->aslist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name); - filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->aslist[direct].aslist = as_list_lookup (name); - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - } - return 0; -} - -int -peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct) -{ - struct bgp_filter *filter; - struct bgp_filter *gfilter; - struct peer_group *group; - struct listnode *node, *nnode; - - if (direct != FILTER_IN && direct != FILTER_OUT) - return BGP_ERR_INVALID_VALUE; - - filter = &peer->filter[afi][safi]; - - /* apply peer-group filter */ - if (peer_group_active(peer)) - { - gfilter = &peer->group->conf->filter[afi][safi]; - - if (gfilter->aslist[direct].name) - { - if (filter->aslist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name); - filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->aslist[direct].name); - filter->aslist[direct].aslist = gfilter->aslist[direct].aslist; - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } - } - - if (filter->aslist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name); - filter->aslist[direct].name = NULL; - filter->aslist[direct].aslist = NULL; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; - - if (filter->aslist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name); - filter->aslist[direct].name = NULL; - filter->aslist[direct].aslist = NULL; - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - } - - return 0; -} - -static void -peer_aslist_update (const char *aslist_name) -{ - afi_t afi; - safi_t safi; - int direct; - struct listnode *mnode, *mnnode; - struct listnode *node, *nnode; - struct bgp *bgp; - struct peer *peer; - struct peer_group *group; - struct bgp_filter *filter; - - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) - { - update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, aslist_name, - 0, 0); - - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { + if (filter->aslist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->aslist[direct].name); + filter->aslist[direct].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->aslist[direct].aslist = as_list_lookup(name); + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + } + return 0; +} + +int peer_aslist_unset(struct peer *peer, afi_t afi, safi_t safi, int direct) +{ + struct bgp_filter *filter; + struct bgp_filter *gfilter; + struct peer_group *group; + struct listnode *node, *nnode; + + if (direct != FILTER_IN && direct != FILTER_OUT) + return BGP_ERR_INVALID_VALUE; + + filter = &peer->filter[afi][safi]; + + /* apply peer-group filter */ + if (peer_group_active(peer)) { + gfilter = &peer->group->conf->filter[afi][safi]; + + if (gfilter->aslist[direct].name) { + if (filter->aslist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->aslist[direct].name); + filter->aslist[direct].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, + gfilter->aslist[direct].name); + filter->aslist[direct].aslist = + gfilter->aslist[direct].aslist; + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } + } + + if (filter->aslist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name); + filter->aslist[direct].name = NULL; + filter->aslist[direct].aslist = NULL; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { filter = &peer->filter[afi][safi]; - for (direct = FILTER_IN; direct < FILTER_MAX; direct++) - { - if (filter->aslist[direct].name) - filter->aslist[direct].aslist = - as_list_lookup (filter->aslist[direct].name); - else - filter->aslist[direct].aslist = NULL; - } - } - } - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - filter = &group->conf->filter[afi][safi]; + if (filter->aslist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->aslist[direct].name); + filter->aslist[direct].name = NULL; + filter->aslist[direct].aslist = NULL; + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + } + + return 0; +} - for (direct = FILTER_IN; direct < FILTER_MAX; direct++) - { - if (filter->aslist[direct].name) - filter->aslist[direct].aslist = - as_list_lookup (filter->aslist[direct].name); - else - filter->aslist[direct].aslist = NULL; - } - } +static void peer_aslist_update(const char *aslist_name) +{ + afi_t afi; + safi_t safi; + int direct; + struct listnode *mnode, *mnnode; + struct listnode *node, *nnode; + struct bgp *bgp; + struct peer *peer; + struct peer_group *group; + struct bgp_filter *filter; + + for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) { + update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, + aslist_name, 0, 0); + + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; + safi++) { + filter = &peer->filter[afi][safi]; + + for (direct = FILTER_IN; + direct < FILTER_MAX; direct++) { + if (filter->aslist[direct].name) + filter->aslist[direct] + .aslist = as_list_lookup( + filter->aslist[direct] + .name); + else + filter->aslist[direct] + .aslist = NULL; + } + } + } + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; + safi++) { + filter = + &group->conf->filter[afi][safi]; + + for (direct = FILTER_IN; + direct < FILTER_MAX; direct++) { + if (filter->aslist[direct].name) + filter->aslist[direct] + .aslist = as_list_lookup( + filter->aslist[direct] + .name); + else + filter->aslist[direct] + .aslist = NULL; + } + } + } } - } } -static void -peer_aslist_add (char *aslist_name) +static void peer_aslist_add(char *aslist_name) { - peer_aslist_update (aslist_name); - route_map_notify_dependencies((char *)aslist_name, RMAP_EVENT_ASLIST_ADDED); + peer_aslist_update(aslist_name); + route_map_notify_dependencies((char *)aslist_name, + RMAP_EVENT_ASLIST_ADDED); } -static void -peer_aslist_del (const char *aslist_name) +static void peer_aslist_del(const char *aslist_name) { - peer_aslist_update (aslist_name); - route_map_notify_dependencies(aslist_name, RMAP_EVENT_ASLIST_DELETED); + peer_aslist_update(aslist_name); + route_map_notify_dependencies(aslist_name, RMAP_EVENT_ASLIST_DELETED); } -int -peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct, - const char *name) +int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct, + const char *name) { - struct bgp_filter *filter; - struct peer_group *group; - struct listnode *node, *nnode; + struct bgp_filter *filter; + struct peer_group *group; + struct listnode *node, *nnode; - if (direct != RMAP_IN && direct != RMAP_OUT) - return BGP_ERR_INVALID_VALUE; + if (direct != RMAP_IN && direct != RMAP_OUT) + return BGP_ERR_INVALID_VALUE; - filter = &peer->filter[afi][safi]; + filter = &peer->filter[afi][safi]; - if (filter->map[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); + if (filter->map[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); - filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->map[direct].map = route_map_lookup_by_name (name); + filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->map[direct].map = route_map_lookup_by_name(name); - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, - (direct == RMAP_OUT) ? 1 : 0); - return 0; - } + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, + (direct == RMAP_OUT) ? 1 : 0); + return 0; + } - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + filter = &peer->filter[afi][safi]; - if (filter->map[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); - filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->map[direct].map = route_map_lookup_by_name (name); - peer_on_policy_change(peer, afi, safi, - (direct == RMAP_OUT) ? 1 : 0); - } - return 0; + if (filter->map[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); + filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->map[direct].map = route_map_lookup_by_name(name); + peer_on_policy_change(peer, afi, safi, + (direct == RMAP_OUT) ? 1 : 0); + } + return 0; } /* Unset route-map from the peer. */ -int -peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct) +int peer_route_map_unset(struct peer *peer, afi_t afi, safi_t safi, int direct) { - struct bgp_filter *filter; - struct bgp_filter *gfilter; - struct peer_group *group; - struct listnode *node, *nnode; + struct bgp_filter *filter; + struct bgp_filter *gfilter; + struct peer_group *group; + struct listnode *node, *nnode; - if (direct != RMAP_IN && direct != RMAP_OUT) - return BGP_ERR_INVALID_VALUE; + if (direct != RMAP_IN && direct != RMAP_OUT) + return BGP_ERR_INVALID_VALUE; - filter = &peer->filter[afi][safi]; + filter = &peer->filter[afi][safi]; - /* apply peer-group filter */ - if (peer_group_active(peer)) - { - gfilter = &peer->group->conf->filter[afi][safi]; + /* apply peer-group filter */ + if (peer_group_active(peer)) { + gfilter = &peer->group->conf->filter[afi][safi]; + + if (gfilter->map[direct].name) { + if (filter->map[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->map[direct].name); + filter->map[direct].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, + gfilter->map[direct].name); + filter->map[direct].map = gfilter->map[direct].map; + peer_on_policy_change(peer, afi, safi, + (direct == RMAP_OUT) ? 1 : 0); + return 0; + } + } - if (gfilter->map[direct].name) - { - if (filter->map[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); - filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->map[direct].name); - filter->map[direct].map = gfilter->map[direct].map; - peer_on_policy_change(peer, afi, safi, - (direct == RMAP_OUT) ? 1 : 0); - return 0; - } - } - - if (filter->map[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); - filter->map[direct].name = NULL; - filter->map[direct].map = NULL; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, - (direct == RMAP_OUT) ? 1 : 0); - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; - - if (filter->map[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); - filter->map[direct].name = NULL; - filter->map[direct].map = NULL; - peer_on_policy_change(peer, afi, safi, - (direct == RMAP_OUT) ? 1 : 0); - } - return 0; + if (filter->map[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); + filter->map[direct].name = NULL; + filter->map[direct].map = NULL; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, + (direct == RMAP_OUT) ? 1 : 0); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + filter = &peer->filter[afi][safi]; + + if (filter->map[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); + filter->map[direct].name = NULL; + filter->map[direct].map = NULL; + peer_on_policy_change(peer, afi, safi, + (direct == RMAP_OUT) ? 1 : 0); + } + return 0; } /* Set unsuppress-map to the peer. */ -int -peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi, - const char *name) -{ - struct bgp_filter *filter; - struct peer_group *group; - struct listnode *node, *nnode; - - filter = &peer->filter[afi][safi]; - - if (filter->usmap.name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); - - filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->usmap.map = route_map_lookup_by_name (name); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, 1); - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; - - if (filter->usmap.name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); - filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->usmap.map = route_map_lookup_by_name (name); - peer_on_policy_change(peer, afi, safi, 1); - } - return 0; +int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi, + const char *name) +{ + struct bgp_filter *filter; + struct peer_group *group; + struct listnode *node, *nnode; + + filter = &peer->filter[afi][safi]; + + if (filter->usmap.name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); + + filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->usmap.map = route_map_lookup_by_name(name); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, 1); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + filter = &peer->filter[afi][safi]; + + if (filter->usmap.name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); + filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->usmap.map = route_map_lookup_by_name(name); + peer_on_policy_change(peer, afi, safi, 1); + } + return 0; } /* Unset route-map from the peer. */ -int -peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi) -{ - struct bgp_filter *filter; - struct peer_group *group; - struct listnode *node, *nnode; - - filter = &peer->filter[afi][safi]; - - if (filter->usmap.name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); - filter->usmap.name = NULL; - filter->usmap.map = NULL; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, 1); - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; - - if (filter->usmap.name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); - filter->usmap.name = NULL; - filter->usmap.map = NULL; - peer_on_policy_change(peer, afi, safi, 1); - } - return 0; -} - -int -peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi, - u_int32_t max, u_char threshold, - int warning, u_int16_t restart) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); - peer->pmax[afi][safi] = max; - peer->pmax_threshold[afi][safi] = threshold; - peer->pmax_restart[afi][safi] = restart; - if (warning) - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - else - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); - peer->pmax[afi][safi] = max; - peer->pmax_threshold[afi][safi] = threshold; - peer->pmax_restart[afi][safi] = restart; - if (warning) - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - else - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - - if ((peer->status == Established) && (peer->afc[afi][safi])) - bgp_maximum_prefix_overflow (peer, afi, safi, 1); - } - } - else - { - if ((peer->status == Established) && (peer->afc[afi][safi])) - bgp_maximum_prefix_overflow (peer, afi, safi, 1); - } - - return 0; -} - -int -peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - /* apply peer-group config */ - if (peer_group_active(peer)) - { - if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], - PEER_FLAG_MAX_PREFIX)) - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); - else - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); - - if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], - PEER_FLAG_MAX_PREFIX_WARNING)) - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - else - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - - peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi]; - peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi]; - peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi]; - return 0; - } - - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - peer->pmax[afi][safi] = 0; - peer->pmax_threshold[afi][safi] = 0; - peer->pmax_restart[afi][safi] = 0; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - peer->pmax[afi][safi] = 0; - peer->pmax_threshold[afi][safi] = 0; - peer->pmax_restart[afi][safi] = 0; - } - return 0; -} - -int is_ebgp_multihop_configured (struct peer *peer) -{ - struct peer_group *group; - struct listnode *node, *nnode; - struct peer *peer1; - - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - group = peer->group; - if ((peer_sort(peer) != BGP_PEER_IBGP) && - (group->conf->ttl != 1)) - return 1; - - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1)) - { - if ((peer_sort (peer1) != BGP_PEER_IBGP) && - (peer1->ttl != 1)) - return 1; +int peer_unsuppress_map_unset(struct peer *peer, afi_t afi, safi_t safi) +{ + struct bgp_filter *filter; + struct peer_group *group; + struct listnode *node, *nnode; + + filter = &peer->filter[afi][safi]; + + if (filter->usmap.name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); + filter->usmap.name = NULL; + filter->usmap.map = NULL; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, 1); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + filter = &peer->filter[afi][safi]; + + if (filter->usmap.name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); + filter->usmap.name = NULL; + filter->usmap.map = NULL; + peer_on_policy_change(peer, afi, safi, 1); } - } - else - { - if ((peer_sort(peer) != BGP_PEER_IBGP) && - (peer->ttl != 1)) - return 1; - } - return 0; + return 0; } -/* Set # of hops between us and BGP peer. */ -int -peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops) -{ - struct peer_group *group; - struct listnode *node, *nnode; - int ret; +int peer_maximum_prefix_set(struct peer *peer, afi_t afi, safi_t safi, + u_int32_t max, u_char threshold, int warning, + u_int16_t restart) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); + peer->pmax[afi][safi] = max; + peer->pmax_threshold[afi][safi] = threshold; + peer->pmax_restart[afi][safi] = restart; + if (warning) + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING); + else + UNSET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING); + + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX); + peer->pmax[afi][safi] = max; + peer->pmax_threshold[afi][safi] = threshold; + peer->pmax_restart[afi][safi] = restart; + if (warning) + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING); + else + UNSET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING); + + if ((peer->status == Established) + && (peer->afc[afi][safi])) + bgp_maximum_prefix_overflow(peer, afi, safi, 1); + } + } else { + if ((peer->status == Established) && (peer->afc[afi][safi])) + bgp_maximum_prefix_overflow(peer, afi, safi, 1); + } - zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host); + return 0; +} - /* We cannot configure ttl-security hops when ebgp-multihop is already - set. For non peer-groups, the check is simple. For peer-groups, it's - slightly messy, because we need to check both the peer-group structure - and all peer-group members for any trace of ebgp-multihop configuration - before actually applying the ttl-security rules. Cisco really made a - mess of this configuration parameter, and OpenBGPD got it right. - */ +int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + /* apply peer-group config */ + if (peer_group_active(peer)) { + if (CHECK_FLAG(peer->group->conf->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX)) + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX); + else + UNSET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX); + + if (CHECK_FLAG(peer->group->conf->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING)) + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING); + else + UNSET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING); + + peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi]; + peer->pmax_threshold[afi][safi] = + peer->group->conf->pmax_threshold[afi][safi]; + peer->pmax_restart[afi][safi] = + peer->group->conf->pmax_restart[afi][safi]; + return 0; + } - if ((peer->gtsm_hops == 0) && (peer->sort != BGP_PEER_IBGP)) - { - if (is_ebgp_multihop_configured (peer)) - return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; + UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); + UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); + peer->pmax[afi][safi] = 0; + peer->pmax_threshold[afi][safi] = 0; + peer->pmax_restart[afi][safi] = 0; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); + UNSET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING); + peer->pmax[afi][safi] = 0; + peer->pmax_threshold[afi][safi] = 0; + peer->pmax_restart[afi][safi] = 0; + } + return 0; +} - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer->gtsm_hops = gtsm_hops; +int is_ebgp_multihop_configured(struct peer *peer) +{ + struct peer_group *group; + struct listnode *node, *nnode; + struct peer *peer1; - /* Calling ebgp multihop also resets the session. - * On restart, NHT will get setup correctly as will the - * min & max ttls on the socket. The return value is - * irrelevant. - */ - ret = peer_ebgp_multihop_set (peer, MAXTTL); + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + group = peer->group; + if ((peer_sort(peer) != BGP_PEER_IBGP) + && (group->conf->ttl != 1)) + return 1; - if (ret != 0) - return ret; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer1)) { + if ((peer_sort(peer1) != BGP_PEER_IBGP) + && (peer1->ttl != 1)) + return 1; + } + } else { + if ((peer_sort(peer) != BGP_PEER_IBGP) && (peer->ttl != 1)) + return 1; } - else - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - peer->gtsm_hops = group->conf->gtsm_hops; - - /* Calling ebgp multihop also resets the session. - * On restart, NHT will get setup correctly as will the - * min & max ttls on the socket. The return value is - * irrelevant. - */ - peer_ebgp_multihop_set (peer, MAXTTL); - } - } - } - else - { - /* Post the first gtsm setup or if its ibgp, maxttl setting isn't - * necessary, just set the minttl. - */ - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer->gtsm_hops = gtsm_hops; + return 0; +} - if (peer->fd >= 0) - sockopt_minttl (peer->su.sa.sa_family, peer->fd, - MAXTTL + 1 - gtsm_hops); - if ((peer->status < Established) && peer->doppelganger && - (peer->doppelganger->fd >= 0)) - sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd, - MAXTTL + 1 - gtsm_hops); +/* Set # of hops between us and BGP peer. */ +int peer_ttl_security_hops_set(struct peer *peer, int gtsm_hops) +{ + struct peer_group *group; + struct listnode *node, *nnode; + int ret; + + zlog_debug("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", + gtsm_hops, peer->host); + + /* We cannot configure ttl-security hops when ebgp-multihop is already + set. For non peer-groups, the check is simple. For peer-groups, + it's + slightly messy, because we need to check both the peer-group + structure + and all peer-group members for any trace of ebgp-multihop + configuration + before actually applying the ttl-security rules. Cisco really made a + mess of this configuration parameter, and OpenBGPD got it right. + */ + + if ((peer->gtsm_hops == 0) && (peer->sort != BGP_PEER_IBGP)) { + if (is_ebgp_multihop_configured(peer)) + return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer->gtsm_hops = gtsm_hops; + + /* Calling ebgp multihop also resets the session. + * On restart, NHT will get setup correctly as will the + * min & max ttls on the socket. The return value is + * irrelevant. + */ + ret = peer_ebgp_multihop_set(peer, MAXTTL); + + if (ret != 0) + return ret; + } else { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, + peer)) { + peer->gtsm_hops = group->conf->gtsm_hops; + + /* Calling ebgp multihop also resets the + * session. + * On restart, NHT will get setup correctly as + * will the + * min & max ttls on the socket. The return + * value is + * irrelevant. + */ + peer_ebgp_multihop_set(peer, MAXTTL); + } + } + } else { + /* Post the first gtsm setup or if its ibgp, maxttl setting + * isn't + * necessary, just set the minttl. + */ + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer->gtsm_hops = gtsm_hops; + + if (peer->fd >= 0) + sockopt_minttl(peer->su.sa.sa_family, peer->fd, + MAXTTL + 1 - gtsm_hops); + if ((peer->status < Established) && peer->doppelganger + && (peer->doppelganger->fd >= 0)) + sockopt_minttl(peer->su.sa.sa_family, + peer->doppelganger->fd, + MAXTTL + 1 - gtsm_hops); + } else { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, + peer)) { + peer->gtsm_hops = group->conf->gtsm_hops; + + /* Change setting of existing peer + * established then change value (may break + * connectivity) + * not established yet (teardown session and + * restart) + * no session then do nothing (will get + * handled by next connection) + */ + if (peer->fd >= 0 && peer->gtsm_hops != 0) + sockopt_minttl( + peer->su.sa.sa_family, peer->fd, + MAXTTL + 1 - peer->gtsm_hops); + if ((peer->status < Established) + && peer->doppelganger + && (peer->doppelganger->fd >= 0)) + sockopt_minttl(peer->su.sa.sa_family, + peer->doppelganger->fd, + MAXTTL + 1 - gtsm_hops); + } + } } - else - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - peer->gtsm_hops = group->conf->gtsm_hops; - - /* Change setting of existing peer - * established then change value (may break connectivity) - * not established yet (teardown session and restart) - * no session then do nothing (will get handled by next connection) - */ - if (peer->fd >= 0 && peer->gtsm_hops != 0) - sockopt_minttl (peer->su.sa.sa_family, peer->fd, - MAXTTL + 1 - peer->gtsm_hops); - if ((peer->status < Established) && peer->doppelganger && - (peer->doppelganger->fd >= 0)) - sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd, - MAXTTL + 1 - gtsm_hops); - - } - } - } - - return 0; -} - -int -peer_ttl_security_hops_unset (struct peer *peer) -{ - struct peer_group *group; - struct listnode *node, *nnode; - int ret = 0; - - zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host); - - /* if a peer-group member, then reset to peer-group default rather than 0 */ - if (peer_group_active (peer)) - peer->gtsm_hops = peer->group->conf->gtsm_hops; - else - peer->gtsm_hops = 0; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - /* Invoking ebgp_multihop_set will set the TTL back to the original - * value as well as restting the NHT and such. The session is reset. - */ - if (peer->sort == BGP_PEER_EBGP) - ret = peer_ebgp_multihop_unset (peer); - else - { - if (peer->fd >= 0) - sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0); - - if ((peer->status < Established) && peer->doppelganger && - (peer->doppelganger->fd >= 0)) - sockopt_minttl (peer->su.sa.sa_family, - peer->doppelganger->fd, 0); - } - } - else - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - peer->gtsm_hops = 0; - if (peer->sort == BGP_PEER_EBGP) - ret = peer_ebgp_multihop_unset (peer); - else - { - if (peer->fd >= 0) - sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0); - if ((peer->status < Established) && peer->doppelganger && - (peer->doppelganger->fd >= 0)) - sockopt_minttl (peer->su.sa.sa_family, - peer->doppelganger->fd, 0); - } + return 0; +} + +int peer_ttl_security_hops_unset(struct peer *peer) +{ + struct peer_group *group; + struct listnode *node, *nnode; + int ret = 0; + + zlog_debug("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", + peer->host); + + /* if a peer-group member, then reset to peer-group default rather than + * 0 */ + if (peer_group_active(peer)) + peer->gtsm_hops = peer->group->conf->gtsm_hops; + else + peer->gtsm_hops = 0; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + /* Invoking ebgp_multihop_set will set the TTL back to the + * original + * value as well as restting the NHT and such. The session is + * reset. + */ + if (peer->sort == BGP_PEER_EBGP) + ret = peer_ebgp_multihop_unset(peer); + else { + if (peer->fd >= 0) + sockopt_minttl(peer->su.sa.sa_family, peer->fd, + 0); + + if ((peer->status < Established) && peer->doppelganger + && (peer->doppelganger->fd >= 0)) + sockopt_minttl(peer->su.sa.sa_family, + peer->doppelganger->fd, 0); + } + } else { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + peer->gtsm_hops = 0; + if (peer->sort == BGP_PEER_EBGP) + ret = peer_ebgp_multihop_unset(peer); + else { + if (peer->fd >= 0) + sockopt_minttl(peer->su.sa.sa_family, + peer->fd, 0); + + if ((peer->status < Established) + && peer->doppelganger + && (peer->doppelganger->fd >= 0)) + sockopt_minttl(peer->su.sa.sa_family, + peer->doppelganger->fd, + 0); + } + } } - } - return ret; + return ret; } /* @@ -6290,1552 +5964,1543 @@ peer_ttl_security_hops_unset (struct peer *peer) * Pass along additional parameter which can be updated if next node * is freed; only required when walking the peer list on BGP instance. */ -int -peer_clear (struct peer *peer, struct listnode **nnode) +int peer_clear(struct peer *peer, struct listnode **nnode) +{ + if (!CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) { + if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)) { + UNSET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW); + if (peer->t_pmax_restart) { + BGP_TIMER_OFF(peer->t_pmax_restart); + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Maximum-prefix restart timer canceled", + peer->host); + } + BGP_EVENT_ADD(peer, BGP_Start); + return 0; + } + + peer->v_start = BGP_INIT_START_TIMER; + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_ADMIN_RESET); + else + bgp_session_reset_safe(peer, nnode); + } + return 0; +} + +int peer_clear_soft(struct peer *peer, afi_t afi, safi_t safi, + enum bgp_clear_type stype) { - if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN)) - { - if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)) - { - UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW); - if (peer->t_pmax_restart) - { - BGP_TIMER_OFF (peer->t_pmax_restart); - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Maximum-prefix restart timer canceled", - peer->host); - } - BGP_EVENT_ADD (peer, BGP_Start); - return 0; - } - - peer->v_start = BGP_INIT_START_TIMER; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_ADMIN_RESET); - else - bgp_session_reset_safe(peer, nnode); - } - return 0; -} - -int -peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi, - enum bgp_clear_type stype) -{ - struct peer_af *paf; - - if (peer->status != Established) - return 0; - - if (! peer->afc[afi][safi]) - return BGP_ERR_AF_UNCONFIGURED; - - peer->rtt = sockopt_tcp_rtt (peer->fd); - - if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH) - { - /* Clear the "neighbor x.x.x.x default-originate" flag */ - paf = peer_af_find (peer, afi, safi); - if (paf && paf->subgroup && - CHECK_FLAG (paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) - UNSET_FLAG (paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE); - - bgp_announce_route (peer, afi, safi); - } - - if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) - { - if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV) - && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV) - || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))) - { - struct bgp_filter *filter = &peer->filter[afi][safi]; - u_char prefix_type; - - if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)) - prefix_type = ORF_TYPE_PREFIX; - else - prefix_type = ORF_TYPE_PREFIX_OLD; - - if (filter->plist[FILTER_IN].plist) - { - if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND)) - bgp_route_refresh_send (peer, afi, safi, - prefix_type, REFRESH_DEFER, 1); - bgp_route_refresh_send (peer, afi, safi, prefix_type, - REFRESH_IMMEDIATE, 0); - } - else - { - if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND)) - bgp_route_refresh_send (peer, afi, safi, - prefix_type, REFRESH_IMMEDIATE, 1); - else - bgp_route_refresh_send (peer, afi, safi, 0, 0, 0); - } - return 0; - } - } - - if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH - || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) - { - /* If neighbor has soft reconfiguration inbound flag. - Use Adj-RIB-In database. */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) - bgp_soft_reconfig_in (peer, afi, safi); - else - { - /* If neighbor has route refresh capability, send route refresh - message to the peer. */ - if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV) - || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV)) - bgp_route_refresh_send (peer, afi, safi, 0, 0, 0); - else - return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED; + struct peer_af *paf; + + if (peer->status != Established) + return 0; + + if (!peer->afc[afi][safi]) + return BGP_ERR_AF_UNCONFIGURED; + + peer->rtt = sockopt_tcp_rtt(peer->fd); + + if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH) { + /* Clear the "neighbor x.x.x.x default-originate" flag */ + paf = peer_af_find(peer, afi, safi); + if (paf && paf->subgroup + && CHECK_FLAG(paf->subgroup->sflags, + SUBGRP_STATUS_DEFAULT_ORIGINATE)) + UNSET_FLAG(paf->subgroup->sflags, + SUBGRP_STATUS_DEFAULT_ORIGINATE); + + bgp_announce_route(peer, afi, safi); } - } - return 0; + + if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) { + if (CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_ADV) + && (CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_RCV) + || CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_OLD_RCV))) { + struct bgp_filter *filter = &peer->filter[afi][safi]; + u_char prefix_type; + + if (CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_RCV)) + prefix_type = ORF_TYPE_PREFIX; + else + prefix_type = ORF_TYPE_PREFIX_OLD; + + if (filter->plist[FILTER_IN].plist) { + if (CHECK_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_ORF_PREFIX_SEND)) + bgp_route_refresh_send( + peer, afi, safi, prefix_type, + REFRESH_DEFER, 1); + bgp_route_refresh_send(peer, afi, safi, + prefix_type, + REFRESH_IMMEDIATE, 0); + } else { + if (CHECK_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_ORF_PREFIX_SEND)) + bgp_route_refresh_send( + peer, afi, safi, prefix_type, + REFRESH_IMMEDIATE, 1); + else + bgp_route_refresh_send(peer, afi, safi, + 0, 0, 0); + } + return 0; + } + } + + if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH + || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) { + /* If neighbor has soft reconfiguration inbound flag. + Use Adj-RIB-In database. */ + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SOFT_RECONFIG)) + bgp_soft_reconfig_in(peer, afi, safi); + else { + /* If neighbor has route refresh capability, send route + refresh + message to the peer. */ + if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV) + || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV)) + bgp_route_refresh_send(peer, afi, safi, 0, 0, + 0); + else + return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED; + } + } + return 0; } /* Display peer uptime.*/ -char * -peer_uptime (time_t uptime2, char *buf, size_t len, u_char use_json, json_object *json) -{ - time_t uptime1, epoch_tbuf; - struct tm *tm; - - /* Check buffer length. */ - if (len < BGP_UPTIME_LEN) - { - if (!use_json) - { - zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len); - /* XXX: should return status instead of buf... */ - snprintf (buf, len, "<error> "); - } - return buf; - } - - /* If there is no connection has been done before print `never'. */ - if (uptime2 == 0) - { - if (use_json) - { - json_object_string_add(json, "peerUptime", "never"); - json_object_int_add(json, "peerUptimeMsec", 0); - } - else - snprintf (buf, len, "never"); - return buf; - } - - /* Get current time. */ - uptime1 = bgp_clock (); - uptime1 -= uptime2; - tm = gmtime (&uptime1); - - /* Making formatted timer strings. */ +char *peer_uptime(time_t uptime2, char *buf, size_t len, u_char use_json, + json_object *json) +{ + time_t uptime1, epoch_tbuf; + struct tm *tm; + + /* Check buffer length. */ + if (len < BGP_UPTIME_LEN) { + if (!use_json) { + zlog_warn("peer_uptime (): buffer shortage %lu", + (u_long)len); + /* XXX: should return status instead of buf... */ + snprintf(buf, len, "<error> "); + } + return buf; + } + + /* If there is no connection has been done before print `never'. */ + if (uptime2 == 0) { + if (use_json) { + json_object_string_add(json, "peerUptime", "never"); + json_object_int_add(json, "peerUptimeMsec", 0); + } else + snprintf(buf, len, "never"); + return buf; + } + + /* Get current time. */ + uptime1 = bgp_clock(); + uptime1 -= uptime2; + tm = gmtime(&uptime1); + +/* Making formatted timer strings. */ #define ONE_DAY_SECOND 60*60*24 #define ONE_WEEK_SECOND ONE_DAY_SECOND*7 #define ONE_YEAR_SECOND ONE_DAY_SECOND*365 - if (uptime1 < ONE_DAY_SECOND) - snprintf (buf, len, "%02d:%02d:%02d", - tm->tm_hour, tm->tm_min, tm->tm_sec); - else if (uptime1 < ONE_WEEK_SECOND) - snprintf (buf, len, "%dd%02dh%02dm", - tm->tm_yday, tm->tm_hour, tm->tm_min); - else if (uptime1 < ONE_YEAR_SECOND) - snprintf (buf, len, "%02dw%dd%02dh", - tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); - else - snprintf (buf, len, "%02dy%02dw%dd", - tm->tm_year - 70, tm->tm_yday/7, - tm->tm_yday - ((tm->tm_yday/7) * 7)); - - if (use_json) - { - epoch_tbuf = time(NULL) - uptime1; - json_object_string_add(json, "peerUptime", buf); - json_object_int_add(json, "peerUptimeMsec", uptime1 * 1000); - json_object_int_add(json, "peerUptimeEstablishedEpoch", epoch_tbuf); - } - - return buf; -} - -static void -afi_header_vty_out (struct vty *vty, afi_t afi, safi_t safi, - int *write, const char *format, ...) -{ - va_list args; - int len = 0; - char buf[1024]; - - bgp_config_write_family_header (vty, afi, safi, write); - - if (vty_shell (vty)) - { - va_start (args, format); - vprintf (format, args); - va_end (args); - } - else - { - va_start (args, format); - len = vsnprintf (buf, sizeof(buf), format, args); - va_end (args); - - buffer_put (vty->obuf, (u_char *) buf, len); - } -} - -static void -bgp_config_write_filter (struct vty *vty, struct peer *peer, - afi_t afi, safi_t safi, int *write) -{ - struct bgp_filter *filter; - struct bgp_filter *gfilter = NULL; - char *addr; - int in = FILTER_IN; - int out = FILTER_OUT; - - addr = peer->host; - filter = &peer->filter[afi][safi]; - - if (peer_group_active(peer)) - gfilter = &peer->group->conf->filter[afi][safi]; - - /* distribute-list. */ - if (filter->dlist[in].name) - if (! gfilter || ! gfilter->dlist[in].name - || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s distribute-list %s in\n", - addr, filter->dlist[in].name); - } - - if (filter->dlist[out].name && ! gfilter) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s distribute-list %s out\n", - addr, filter->dlist[out].name); - } - - /* prefix-list. */ - if (filter->plist[in].name) - if (! gfilter || ! gfilter->plist[in].name - || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s prefix-list %s in\n", - addr, filter->plist[in].name); - } - - if (filter->plist[out].name && ! gfilter) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s prefix-list %s out\n", - addr, filter->plist[out].name); - } - - /* route-map. */ - if (filter->map[RMAP_IN].name) - if (! gfilter || ! gfilter->map[RMAP_IN].name - || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s route-map %s in\n", - addr, filter->map[RMAP_IN].name); - } - - if (filter->map[RMAP_OUT].name) - if (! gfilter || ! gfilter->map[RMAP_OUT].name - || strcmp (filter->map[RMAP_OUT].name, gfilter->map[RMAP_OUT].name) != 0) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s route-map %s out\n", - addr, filter->map[RMAP_OUT].name); - } - - /* unsuppress-map */ - if (filter->usmap.name && ! gfilter) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s unsuppress-map %s\n", - addr, filter->usmap.name); - } - - /* filter-list. */ - if (filter->aslist[in].name) - if (! gfilter || ! gfilter->aslist[in].name - || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s filter-list %s in\n", - addr, filter->aslist[in].name); - } - - if (filter->aslist[out].name && ! gfilter) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s filter-list %s out\n", - addr, filter->aslist[out].name); - } + if (uptime1 < ONE_DAY_SECOND) + snprintf(buf, len, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, + tm->tm_sec); + else if (uptime1 < ONE_WEEK_SECOND) + snprintf(buf, len, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour, + tm->tm_min); + else if (uptime1 < ONE_YEAR_SECOND) + snprintf(buf, len, "%02dw%dd%02dh", tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour); + else + snprintf(buf, len, "%02dy%02dw%dd", tm->tm_year - 70, + tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7)); + + if (use_json) { + epoch_tbuf = time(NULL) - uptime1; + json_object_string_add(json, "peerUptime", buf); + json_object_int_add(json, "peerUptimeMsec", uptime1 * 1000); + json_object_int_add(json, "peerUptimeEstablishedEpoch", + epoch_tbuf); + } + + return buf; } -/* BGP peer configuration display function. */ -static void -bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, - struct peer *peer) -{ - struct peer *g_peer = NULL; - char buf[SU_ADDRSTRLEN]; - char *addr; - int if_pg_printed = FALSE; - int if_ras_printed = FALSE; - - /* Skip dynamic neighbors. */ - if (peer_dynamic_neighbor (peer)) - return; - - if (peer->conf_if) - addr = peer->conf_if; - else - addr = peer->host; - - /************************************ - ****** Global to the neighbor ****** - ************************************/ - if (peer->conf_if) - { - if (CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) - vty_out (vty, " neighbor %s interface v6only", addr); - else - vty_out (vty, " neighbor %s interface", addr); - - if (peer_group_active (peer)) - { - vty_out (vty, " peer-group %s", peer->group->name); - if_pg_printed = TRUE; - } - else if (peer->as_type == AS_SPECIFIED) - { - vty_out (vty, " remote-as %u", peer->as); - if_ras_printed = TRUE; - } - else if (peer->as_type == AS_INTERNAL) - { - vty_out (vty, " remote-as internal"); - if_ras_printed = TRUE; - } - else if (peer->as_type == AS_EXTERNAL) - { - vty_out (vty, " remote-as external"); - if_ras_printed = TRUE; - } - - vty_out (vty, "\n"); - } - - /* remote-as and peer-group */ - /* peer is a member of a peer-group */ - if (peer_group_active (peer)) - { - g_peer = peer->group->conf; - - if (g_peer->as_type == AS_UNSPECIFIED && !if_ras_printed) - { - if (peer->as_type == AS_SPECIFIED) - { - vty_out (vty, " neighbor %s remote-as %u\n", addr,peer->as); - } - else if (peer->as_type == AS_INTERNAL) - { - vty_out (vty, " neighbor %s remote-as internal\n", addr); - } - else if (peer->as_type == AS_EXTERNAL) - { - vty_out (vty, " neighbor %s remote-as external\n", addr); - } - } - - /* For swpX peers we displayed the peer-group - * via 'neighbor swpX interface peer-group WORD' */ - if (!if_pg_printed) - vty_out (vty, " neighbor %s peer-group %s\n", addr, - peer->group->name); - } - - /* peer is NOT a member of a peer-group */ - else - { - /* peer is a peer-group, declare the peer-group */ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - vty_out (vty, " neighbor %s peer-group\n",addr); - } - - if (!if_ras_printed) - { - if (peer->as_type == AS_SPECIFIED) - { - vty_out (vty, " neighbor %s remote-as %u\n", addr,peer->as); - } - else if (peer->as_type == AS_INTERNAL) - { - vty_out (vty, " neighbor %s remote-as internal\n", addr); - } - else if (peer->as_type == AS_EXTERNAL) - { - vty_out (vty, " neighbor %s remote-as external\n", addr); - } - } - } - - /* local-as */ - if (peer->change_local_as) - { - if (! peer_group_active (peer) - || peer->change_local_as != g_peer->change_local_as - || (CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) != - CHECK_FLAG (g_peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) - || (CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) != - CHECK_FLAG (g_peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS))) - { - vty_out (vty, " neighbor %s local-as %u%s%s\n", addr, - peer->change_local_as, - CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ? - " no-prepend" : "", - CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ? " replace-as" : ""); - } - } - - /* description */ - if (peer->desc) - { - vty_out (vty, " neighbor %s description %s\n", addr,peer->desc); - } - - /* shutdown */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN) || - peer->tx_shutdown_message) - { - if (peer->tx_shutdown_message) - vty_out (vty, " neighbor %s shutdown message %s\n", addr, - peer->tx_shutdown_message); - else - vty_out (vty, " neighbor %s shutdown\n", addr); - } - } - - /* bfd */ - if (peer->bfd_info) - { - if (! peer_group_active (peer) || ! g_peer->bfd_info) - { - bgp_bfd_peer_config_write(vty, peer, addr); - } - } - - /* password */ - if (peer->password) - { - if (!peer_group_active (peer) - || ! g_peer->password - || strcmp (peer->password, g_peer->password) != 0) - { - vty_out (vty, " neighbor %s password %s\n", addr,peer->password); - } - } - - /* neighbor solo */ - if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)) - { - if (!peer_group_active (peer)) - { - vty_out (vty, " neighbor %s solo\n", addr); - } - } - - /* BGP port */ - if (peer->port != BGP_PORT_DEFAULT) - { - vty_out (vty, " neighbor %s port %d\n", addr,peer->port); - } - - /* Local interface name */ - if (peer->ifname) - { - vty_out (vty, " neighbor %s interface %s\n", addr,peer->ifname); - } - - /* passive */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE)) - { - vty_out (vty, " neighbor %s passive\n", addr); - } - } - - /* ebgp-multihop */ - if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 && - !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL)) - { - if (! peer_group_active (peer) || g_peer->ttl != peer->ttl) - { - vty_out (vty, " neighbor %s ebgp-multihop %d\n", addr,peer->ttl); - } - } - - /* ttl-security hops */ - if (peer->gtsm_hops != 0) - { - if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops) - { - vty_out (vty, " neighbor %s ttl-security hops %d\n", addr, - peer->gtsm_hops); - } - } - - /* disable-connected-check */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) - { - vty_out (vty, " neighbor %s disable-connected-check\n", addr); - } - } - - /* update-source */ - if (peer->update_if) - { - if (! peer_group_active (peer) || ! g_peer->update_if - || strcmp (g_peer->update_if, peer->update_if) != 0) - { - vty_out (vty, " neighbor %s update-source %s\n", addr, - peer->update_if); - } - } - if (peer->update_source) - { - if (! peer_group_active (peer) || ! g_peer->update_source - || sockunion_cmp (g_peer->update_source, - peer->update_source) != 0) - { - vty_out (vty, " neighbor %s update-source %s\n", addr, - sockunion2str(peer->update_source, buf, SU_ADDRSTRLEN)); - } - } - - /* advertisement-interval */ - if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) && - ((! peer_group_active (peer) && peer->v_routeadv != BGP_DEFAULT_EBGP_ROUTEADV) || - (peer_group_active (peer) && peer->v_routeadv != g_peer->v_routeadv))) - { - vty_out (vty, " neighbor %s advertisement-interval %u\n", - addr, peer->v_routeadv); - } - - /* timers */ - if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER) && - ((! peer_group_active (peer) && (peer->keepalive != BGP_DEFAULT_KEEPALIVE || peer->holdtime != BGP_DEFAULT_HOLDTIME)) || - (peer_group_active (peer) && (peer->keepalive != g_peer->keepalive || peer->holdtime != g_peer->holdtime)))) - { - vty_out (vty, " neighbor %s timers %u %u\n", addr, - peer->keepalive, peer->holdtime); - } - - if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) && - ((! peer_group_active (peer) && peer->connect != BGP_DEFAULT_CONNECT_RETRY) || - (peer_group_active (peer) && peer->connect != g_peer->connect))) - - { - vty_out (vty, " neighbor %s timers connect %u\n", addr, - peer->connect); - } - - /* capability dynamic */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) - { - vty_out (vty, " neighbor %s capability dynamic\n",addr); - } - } - - /* capability extended-nexthop */ - if (peer->ifp && !CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) - { - vty_out (vty, " no neighbor %s capability extended-nexthop\n", - addr); - } - } - - if (!peer->ifp && CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) - { - vty_out (vty, " neighbor %s capability extended-nexthop\n",addr); - } - } - - /* dont-capability-negotiation */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY)) - { - vty_out (vty, " neighbor %s dont-capability-negotiate\n",addr); - } - } - - /* override-capability */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) - { - vty_out (vty, " neighbor %s override-capability\n",addr); - } - } - - /* strict-capability-match */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) - { - vty_out (vty, " neighbor %s strict-capability-match\n",addr); - } - } +static void afi_header_vty_out(struct vty *vty, afi_t afi, safi_t safi, + int *write, const char *format, ...) +{ + va_list args; + int len = 0; + char buf[1024]; + + bgp_config_write_family_header(vty, afi, safi, write); + + if (vty_shell(vty)) { + va_start(args, format); + vprintf(format, args); + va_end(args); + } else { + va_start(args, format); + len = vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + + buffer_put(vty->obuf, (u_char *)buf, len); + } +} + +static void bgp_config_write_filter(struct vty *vty, struct peer *peer, + afi_t afi, safi_t safi, int *write) +{ + struct bgp_filter *filter; + struct bgp_filter *gfilter = NULL; + char *addr; + int in = FILTER_IN; + int out = FILTER_OUT; + + addr = peer->host; + filter = &peer->filter[afi][safi]; + + if (peer_group_active(peer)) + gfilter = &peer->group->conf->filter[afi][safi]; + + /* distribute-list. */ + if (filter->dlist[in].name) + if (!gfilter || !gfilter->dlist[in].name + || strcmp(filter->dlist[in].name, gfilter->dlist[in].name) + != 0) { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s distribute-list %s in\n", addr, + filter->dlist[in].name); + } + + if (filter->dlist[out].name && !gfilter) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s distribute-list %s out\n", + addr, filter->dlist[out].name); + } + + /* prefix-list. */ + if (filter->plist[in].name) + if (!gfilter || !gfilter->plist[in].name + || strcmp(filter->plist[in].name, gfilter->plist[in].name) + != 0) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s prefix-list %s in\n", + addr, filter->plist[in].name); + } + + if (filter->plist[out].name && !gfilter) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s prefix-list %s out\n", addr, + filter->plist[out].name); + } + + /* route-map. */ + if (filter->map[RMAP_IN].name) + if (!gfilter || !gfilter->map[RMAP_IN].name + || strcmp(filter->map[RMAP_IN].name, + gfilter->map[RMAP_IN].name) + != 0) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s route-map %s in\n", + addr, filter->map[RMAP_IN].name); + } + + if (filter->map[RMAP_OUT].name) + if (!gfilter || !gfilter->map[RMAP_OUT].name + || strcmp(filter->map[RMAP_OUT].name, + gfilter->map[RMAP_OUT].name) + != 0) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s route-map %s out\n", + addr, filter->map[RMAP_OUT].name); + } + + /* unsuppress-map */ + if (filter->usmap.name && !gfilter) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s unsuppress-map %s\n", addr, + filter->usmap.name); + } + + /* filter-list. */ + if (filter->aslist[in].name) + if (!gfilter || !gfilter->aslist[in].name + || strcmp(filter->aslist[in].name, gfilter->aslist[in].name) + != 0) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s filter-list %s in\n", + addr, filter->aslist[in].name); + } + + if (filter->aslist[out].name && !gfilter) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s filter-list %s out\n", addr, + filter->aslist[out].name); + } } /* BGP peer configuration display function. */ -static void -bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, - struct peer *peer, afi_t afi, safi_t safi, - int *write) -{ - struct peer *g_peer = NULL; - char *addr; - - /* Skip dynamic neighbors. */ - if (peer_dynamic_neighbor (peer)) - return; - - if (peer->conf_if) - addr = peer->conf_if; - else - addr = peer->host; - - /************************************ - ****** Per AF to the neighbor ****** - ************************************/ - if (peer_group_active (peer)) - { - g_peer = peer->group->conf; - - /* If the peer-group is active but peer is not, print a 'no activate' */ - if (g_peer->afc[afi][safi] && !peer->afc[afi][safi]) - { - afi_header_vty_out (vty, afi, safi, write, - " no neighbor %s activate\n", - addr); - } - - /* If the peer-group is not active but peer is, print an 'activate' */ - else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi]) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s activate\n", - addr); - } - } - else - { - if (peer->afc[afi][safi]) - { - if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) - { - if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)) - { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s activate\n", - addr); - } - } - else - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s activate\n", - addr); - } - else +static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp, + struct peer *peer) +{ + struct peer *g_peer = NULL; + char buf[SU_ADDRSTRLEN]; + char *addr; + int if_pg_printed = FALSE; + int if_ras_printed = FALSE; + + /* Skip dynamic neighbors. */ + if (peer_dynamic_neighbor(peer)) + return; + + if (peer->conf_if) + addr = peer->conf_if; + else + addr = peer->host; + + /************************************ + ****** Global to the neighbor ****** + ************************************/ + if (peer->conf_if) { + if (CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) + vty_out(vty, " neighbor %s interface v6only", addr); + else + vty_out(vty, " neighbor %s interface", addr); + + if (peer_group_active(peer)) { + vty_out(vty, " peer-group %s", peer->group->name); + if_pg_printed = TRUE; + } else if (peer->as_type == AS_SPECIFIED) { + vty_out(vty, " remote-as %u", peer->as); + if_ras_printed = TRUE; + } else if (peer->as_type == AS_INTERNAL) { + vty_out(vty, " remote-as internal"); + if_ras_printed = TRUE; + } else if (peer->as_type == AS_EXTERNAL) { + vty_out(vty, " remote-as external"); + if_ras_printed = TRUE; + } + + vty_out(vty, "\n"); + } + + /* remote-as and peer-group */ + /* peer is a member of a peer-group */ + if (peer_group_active(peer)) { + g_peer = peer->group->conf; + + if (g_peer->as_type == AS_UNSPECIFIED && !if_ras_printed) { + if (peer->as_type == AS_SPECIFIED) { + vty_out(vty, " neighbor %s remote-as %u\n", + addr, peer->as); + } else if (peer->as_type == AS_INTERNAL) { + vty_out(vty, + " neighbor %s remote-as internal\n", + addr); + } else if (peer->as_type == AS_EXTERNAL) { + vty_out(vty, + " neighbor %s remote-as external\n", + addr); + } + } + + /* For swpX peers we displayed the peer-group + * via 'neighbor swpX interface peer-group WORD' */ + if (!if_pg_printed) + vty_out(vty, " neighbor %s peer-group %s\n", addr, + peer->group->name); + } + + /* peer is NOT a member of a peer-group */ + else { + /* peer is a peer-group, declare the peer-group */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + vty_out(vty, " neighbor %s peer-group\n", addr); + } + + if (!if_ras_printed) { + if (peer->as_type == AS_SPECIFIED) { + vty_out(vty, " neighbor %s remote-as %u\n", + addr, peer->as); + } else if (peer->as_type == AS_INTERNAL) { + vty_out(vty, + " neighbor %s remote-as internal\n", + addr); + } else if (peer->as_type == AS_EXTERNAL) { + vty_out(vty, + " neighbor %s remote-as external\n", + addr); + } + } + } + + /* local-as */ + if (peer->change_local_as) { + if (!peer_group_active(peer) + || peer->change_local_as != g_peer->change_local_as + || (CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) + != CHECK_FLAG(g_peer->flags, + PEER_FLAG_LOCAL_AS_NO_PREPEND)) + || (CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) + != CHECK_FLAG(g_peer->flags, + PEER_FLAG_LOCAL_AS_REPLACE_AS))) { + vty_out(vty, " neighbor %s local-as %u%s%s\n", addr, + peer->change_local_as, + CHECK_FLAG(peer->flags, + PEER_FLAG_LOCAL_AS_NO_PREPEND) + ? " no-prepend" + : "", + CHECK_FLAG(peer->flags, + PEER_FLAG_LOCAL_AS_REPLACE_AS) + ? " replace-as" + : ""); + } + } + + /* description */ + if (peer->desc) { + vty_out(vty, " neighbor %s description %s\n", addr, peer->desc); + } + + /* shutdown */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, PEER_FLAG_SHUTDOWN) + || peer->tx_shutdown_message) { + if (peer->tx_shutdown_message) + vty_out(vty, + " neighbor %s shutdown message %s\n", + addr, peer->tx_shutdown_message); + else + vty_out(vty, " neighbor %s shutdown\n", addr); + } + } + + /* bfd */ + if (peer->bfd_info) { + if (!peer_group_active(peer) || !g_peer->bfd_info) { + bgp_bfd_peer_config_write(vty, peer, addr); + } + } + + /* password */ + if (peer->password) { + if (!peer_group_active(peer) || !g_peer->password + || strcmp(peer->password, g_peer->password) != 0) { + vty_out(vty, " neighbor %s password %s\n", addr, + peer->password); + } + } + + /* neighbor solo */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)) { + if (!peer_group_active(peer)) { + vty_out(vty, " neighbor %s solo\n", addr); + } + } + + /* BGP port */ + if (peer->port != BGP_PORT_DEFAULT) { + vty_out(vty, " neighbor %s port %d\n", addr, peer->port); + } + + /* Local interface name */ + if (peer->ifname) { + vty_out(vty, " neighbor %s interface %s\n", addr, peer->ifname); + } + + /* passive */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSIVE)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, PEER_FLAG_PASSIVE)) { + vty_out(vty, " neighbor %s passive\n", addr); + } + } + + /* ebgp-multihop */ + if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 + && !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL)) { + if (!peer_group_active(peer) || g_peer->ttl != peer->ttl) { + vty_out(vty, " neighbor %s ebgp-multihop %d\n", addr, + peer->ttl); + } + } + + /* ttl-security hops */ + if (peer->gtsm_hops != 0) { + if (!peer_group_active(peer) + || g_peer->gtsm_hops != peer->gtsm_hops) { + vty_out(vty, " neighbor %s ttl-security hops %d\n", + addr, peer->gtsm_hops); + } + } + + /* disable-connected-check */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, + PEER_FLAG_DISABLE_CONNECTED_CHECK)) { + vty_out(vty, " neighbor %s disable-connected-check\n", + addr); + } + } + + /* update-source */ + if (peer->update_if) { + if (!peer_group_active(peer) || !g_peer->update_if + || strcmp(g_peer->update_if, peer->update_if) != 0) { + vty_out(vty, " neighbor %s update-source %s\n", addr, + peer->update_if); + } + } + if (peer->update_source) { + if (!peer_group_active(peer) || !g_peer->update_source + || sockunion_cmp(g_peer->update_source, peer->update_source) + != 0) { + vty_out(vty, " neighbor %s update-source %s\n", addr, + sockunion2str(peer->update_source, buf, + SU_ADDRSTRLEN)); + } + } + + /* advertisement-interval */ + if (CHECK_FLAG(peer->config, PEER_CONFIG_ROUTEADV) + && ((!peer_group_active(peer) + && peer->v_routeadv != BGP_DEFAULT_EBGP_ROUTEADV) + || (peer_group_active(peer) + && peer->v_routeadv != g_peer->v_routeadv))) { + vty_out(vty, " neighbor %s advertisement-interval %u\n", addr, + peer->v_routeadv); + } + + /* timers */ + if (CHECK_FLAG(peer->config, PEER_CONFIG_TIMER) + && ((!peer_group_active(peer) + && (peer->keepalive != BGP_DEFAULT_KEEPALIVE + || peer->holdtime != BGP_DEFAULT_HOLDTIME)) + || (peer_group_active(peer) + && (peer->keepalive != g_peer->keepalive + || peer->holdtime != g_peer->holdtime)))) { + vty_out(vty, " neighbor %s timers %u %u\n", addr, + peer->keepalive, peer->holdtime); + } + + if (CHECK_FLAG(peer->config, PEER_CONFIG_CONNECT) + && ((!peer_group_active(peer) + && peer->connect != BGP_DEFAULT_CONNECT_RETRY) + || (peer_group_active(peer) + && peer->connect != g_peer->connect))) + { - if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) - { - if (!bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)) - { - afi_header_vty_out (vty, afi, safi, write, - " no neighbor %s activate\n", - addr); - } - } - } - } - - /* addpath TX knobs */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ADDPATH_TX_ALL_PATHS)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s addpath-tx-all-paths\n", - addr); - } - - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s addpath-tx-bestpath-per-AS\n", - addr); - } - - /* ORF capability. */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) || - peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s capability orf prefix-list", - addr); - - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) && - peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM)) - vty_out (vty, " both"); - else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM)) - vty_out (vty, " send"); - else - vty_out (vty, " receive"); - vty_out (vty, "\n"); - } - - /* Route reflector client. */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s route-reflector-client\n", - addr); - } - - /* next-hop-self force */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_FORCE_NEXTHOP_SELF)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s next-hop-self force\n", - addr); - } - - /* next-hop-self */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s next-hop-self\n", - addr); - } - - /* remove-private-AS */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s remove-private-AS all replace-AS\n", - addr); - } - - else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s remove-private-AS replace-AS\n", - addr); - } - - else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s remove-private-AS all\n", - addr); - } - - else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s remove-private-AS\n", - addr); - } - - /* as-override */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s as-override\n", - addr); - } - - /* send-community print. */ - if (bgp_option_check (BGP_OPT_CONFIG_CISCO)) - { - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) - && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) - && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s send-community all\n", - addr); - } - else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s send-community large\n", - addr); - } - else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s send-community extended\n", - addr); - } - else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s send-community\n", - addr); - } - } - else - { - if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) && - (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)) && - !peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) && - (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) && - !peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY) && - (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY))) - { - afi_header_vty_out (vty, afi, safi, write, - " no neighbor %s send-community all\n", - addr); - } - else - { - if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY) && - (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY))) - { - afi_header_vty_out (vty, afi, safi, write, - " no neighbor %s send-community large\n", - addr); - } - - if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) && - (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))) - { - afi_header_vty_out (vty, afi, safi, write, - " no neighbor %s send-community extended\n", - addr); - } - - if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) && - (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))) - { - afi_header_vty_out (vty, afi, safi, write, - " no neighbor %s send-community\n", - addr); - } - } - } - - /* Default information */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE) || - (g_peer && - ((peer->default_rmap[afi][safi].name && !g_peer->default_rmap[afi][safi].name) || - (!peer->default_rmap[afi][safi].name && g_peer->default_rmap[afi][safi].name) || - (peer->default_rmap[afi][safi].name && - strcmp(peer->default_rmap[afi][safi].name, g_peer->default_rmap[afi][safi].name))))) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s default-originate", addr); - if (peer->default_rmap[afi][safi].name) - vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name); - vty_out (vty, "\n"); - } - - /* Soft reconfiguration inbound. */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s soft-reconfiguration inbound\n", - addr); - } - - /* maximum-prefix. */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) - if (! peer_group_active(peer) - || g_peer->pmax[afi][safi] != peer->pmax[afi][safi] - || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi] - || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING) - != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s maximum-prefix %lu", - addr, peer->pmax[afi][safi]); - if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT) - vty_out (vty, " %u", peer->pmax_threshold[afi][safi]); - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) - vty_out (vty, " warning-only"); - if (peer->pmax_restart[afi][safi]) - vty_out (vty, " restart %u", peer->pmax_restart[afi][safi]); - vty_out (vty, "\n"); - } - - /* Route server client. */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_RSERVER_CLIENT)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s route-server-client\n", - addr); - } - - /* Nexthop-local unchanged. */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s nexthop-local unchanged\n", - addr); - } - - /* allowas-in <1-10> */ - if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN)) - { - if (! peer_group_active (peer) - || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN) - || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi]) - { - if (peer->allowas_in[afi][safi] == 3) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s allowas-in\n", - addr); - } - else - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s allowas-in %d\n", - addr, peer->allowas_in[afi][safi]); - } - } - } - - /* allowas-in origin */ - else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN)) - { - if (! peer_group_active (peer) - || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s allowas-in origin\n", - addr); - } - } - - /* weight */ - if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_WEIGHT)) - if (! peer_group_active (peer) - || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_WEIGHT) - || peer->weight[afi][safi] != g_peer->weight[afi][safi]) - { - if (peer->weight[afi][safi]) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s weight %lu\n", - addr, peer->weight[afi][safi]); - } - } - - /* Filter. */ - bgp_config_write_filter (vty, peer, afi, safi, write); - - /* atribute-unchanged. */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED) - || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED) - || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) - { - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) - && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) - && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s attribute-unchanged\n", - addr); - } - else - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s attribute-unchanged%s%s%s\n", addr, - peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ? - " as-path" : "", - peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) ? - " next-hop" : "", - peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED) ? - " med" : ""); - } - } + vty_out(vty, " neighbor %s timers connect %u\n", addr, + peer->connect); + } + + /* capability dynamic */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, + PEER_FLAG_DYNAMIC_CAPABILITY)) { + vty_out(vty, " neighbor %s capability dynamic\n", addr); + } + } + + /* capability extended-nexthop */ + if (peer->ifp && !CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) { + vty_out(vty, + " no neighbor %s capability extended-nexthop\n", + addr); + } + } + + if (!peer->ifp && CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) { + vty_out(vty, + " neighbor %s capability extended-nexthop\n", + addr); + } + } + + /* dont-capability-negotiation */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_DONT_CAPABILITY)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, PEER_FLAG_DONT_CAPABILITY)) { + vty_out(vty, " neighbor %s dont-capability-negotiate\n", + addr); + } + } + + /* override-capability */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, + PEER_FLAG_OVERRIDE_CAPABILITY)) { + vty_out(vty, " neighbor %s override-capability\n", + addr); + } + } + + /* strict-capability-match */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) { + vty_out(vty, " neighbor %s strict-capability-match\n", + addr); + } + } +} + +/* BGP peer configuration display function. */ +static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, + struct peer *peer, afi_t afi, safi_t safi, + int *write) +{ + struct peer *g_peer = NULL; + char *addr; + + /* Skip dynamic neighbors. */ + if (peer_dynamic_neighbor(peer)) + return; + + if (peer->conf_if) + addr = peer->conf_if; + else + addr = peer->host; + + /************************************ + ****** Per AF to the neighbor ****** + ************************************/ + if (peer_group_active(peer)) { + g_peer = peer->group->conf; + + /* If the peer-group is active but peer is not, print a 'no + * activate' */ + if (g_peer->afc[afi][safi] && !peer->afc[afi][safi]) { + afi_header_vty_out(vty, afi, safi, write, + " no neighbor %s activate\n", addr); + } + + /* If the peer-group is not active but peer is, print an + 'activate' */ + else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi]) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s activate\n", addr); + } + } else { + if (peer->afc[afi][safi]) { + if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) { + if (bgp_flag_check(bgp, + BGP_FLAG_NO_DEFAULT_IPV4)) { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s activate\n", + addr); + } + } else + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s activate\n", + addr); + } else { + if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) { + if (!bgp_flag_check(bgp, + BGP_FLAG_NO_DEFAULT_IPV4)) { + afi_header_vty_out( + vty, afi, safi, write, + " no neighbor %s activate\n", + addr); + } + } + } + } + + /* addpath TX knobs */ + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_ADDPATH_TX_ALL_PATHS)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s addpath-tx-all-paths\n", + addr); + } + + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s addpath-tx-bestpath-per-AS\n", + addr); + } + + /* ORF capability. */ + if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) + || peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_ORF_PREFIX_RM)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s capability orf prefix-list", + addr); + + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_ORF_PREFIX_SM) + && peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_ORF_PREFIX_RM)) + vty_out(vty, " both"); + else if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_ORF_PREFIX_SM)) + vty_out(vty, " send"); + else + vty_out(vty, " receive"); + vty_out(vty, "\n"); + } + + /* Route reflector client. */ + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_REFLECTOR_CLIENT)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s route-reflector-client\n", + addr); + } + + /* next-hop-self force */ + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_FORCE_NEXTHOP_SELF)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s next-hop-self force\n", addr); + } + + /* next-hop-self */ + if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s next-hop-self\n", addr); + } + + /* remove-private-AS */ + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s remove-private-AS all replace-AS\n", + addr); + } + + else if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s remove-private-AS replace-AS\n", addr); + } + + else if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s remove-private-AS all\n", + addr); + } + + else if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_REMOVE_PRIVATE_AS)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s remove-private-AS\n", addr); + } + + /* as-override */ + if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s as-override\n", addr); + } + + /* send-community print. */ + if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) { + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_COMMUNITY) + && peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_EXT_COMMUNITY) + && peergroup_af_flag_check( + peer, afi, safi, + PEER_FLAG_SEND_LARGE_COMMUNITY)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s send-community all\n", + addr); + } else if (peergroup_af_flag_check( + peer, afi, safi, + PEER_FLAG_SEND_LARGE_COMMUNITY)) { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s send-community large\n", addr); + } else if (peergroup_af_flag_check( + peer, afi, safi, + PEER_FLAG_SEND_EXT_COMMUNITY)) { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s send-community extended\n", + addr); + } else if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_COMMUNITY)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s send-community\n", + addr); + } + } else { + if (!peer_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_COMMUNITY) + && (!g_peer || peer_af_flag_check(g_peer, afi, safi, + PEER_FLAG_SEND_COMMUNITY)) + && !peer_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_EXT_COMMUNITY) + && (!g_peer + || peer_af_flag_check(g_peer, afi, safi, + PEER_FLAG_SEND_EXT_COMMUNITY)) + && !peer_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_LARGE_COMMUNITY) + && (!g_peer || peer_af_flag_check( + g_peer, afi, safi, + PEER_FLAG_SEND_LARGE_COMMUNITY))) { + afi_header_vty_out( + vty, afi, safi, write, + " no neighbor %s send-community all\n", addr); + } else { + if (!peer_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_LARGE_COMMUNITY) + && (!g_peer + || peer_af_flag_check( + g_peer, afi, safi, + PEER_FLAG_SEND_LARGE_COMMUNITY))) { + afi_header_vty_out( + vty, afi, safi, write, + " no neighbor %s send-community large\n", + addr); + } + + if (!peer_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_EXT_COMMUNITY) + && (!g_peer + || peer_af_flag_check( + g_peer, afi, safi, + PEER_FLAG_SEND_EXT_COMMUNITY))) { + afi_header_vty_out( + vty, afi, safi, write, + " no neighbor %s send-community extended\n", + addr); + } + + if (!peer_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_COMMUNITY) + && (!g_peer || peer_af_flag_check( + g_peer, afi, safi, + PEER_FLAG_SEND_COMMUNITY))) { + afi_header_vty_out( + vty, afi, safi, write, + " no neighbor %s send-community\n", + addr); + } + } + } + + /* Default information */ + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_DEFAULT_ORIGINATE) + || (g_peer + && ((peer->default_rmap[afi][safi].name + && !g_peer->default_rmap[afi][safi].name) + || (!peer->default_rmap[afi][safi].name + && g_peer->default_rmap[afi][safi].name) + || (peer->default_rmap[afi][safi].name + && strcmp(peer->default_rmap[afi][safi].name, + g_peer->default_rmap[afi][safi].name))))) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s default-originate", addr); + if (peer->default_rmap[afi][safi].name) + vty_out(vty, " route-map %s", + peer->default_rmap[afi][safi].name); + vty_out(vty, "\n"); + } + + /* Soft reconfiguration inbound. */ + if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s soft-reconfiguration inbound\n", addr); + } + + /* maximum-prefix. */ + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) + if (!peer_group_active(peer) + || g_peer->pmax[afi][safi] != peer->pmax[afi][safi] + || g_peer->pmax_threshold[afi][safi] + != peer->pmax_threshold[afi][safi] + || CHECK_FLAG(g_peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING) + != CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s maximum-prefix %lu", + addr, peer->pmax[afi][safi]); + if (peer->pmax_threshold[afi][safi] + != MAXIMUM_PREFIX_THRESHOLD_DEFAULT) + vty_out(vty, " %u", + peer->pmax_threshold[afi][safi]); + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING)) + vty_out(vty, " warning-only"); + if (peer->pmax_restart[afi][safi]) + vty_out(vty, " restart %u", + peer->pmax_restart[afi][safi]); + vty_out(vty, "\n"); + } + + /* Route server client. */ + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_RSERVER_CLIENT)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s route-server-client\n", addr); + } + + /* Nexthop-local unchanged. */ + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s nexthop-local unchanged\n", + addr); + } + + /* allowas-in <1-10> */ + if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_ALLOWAS_IN)) { + if (!peer_group_active(peer) + || !peer_af_flag_check(g_peer, afi, safi, + PEER_FLAG_ALLOWAS_IN) + || peer->allowas_in[afi][safi] + != g_peer->allowas_in[afi][safi]) { + if (peer->allowas_in[afi][safi] == 3) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s allowas-in\n", + addr); + } else { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s allowas-in %d\n", addr, + peer->allowas_in[afi][safi]); + } + } + } + + /* allowas-in origin */ + else if (peer_af_flag_check(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN_ORIGIN)) { + if (!peer_group_active(peer) + || !peer_af_flag_check(g_peer, afi, safi, + PEER_FLAG_ALLOWAS_IN_ORIGIN)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s allowas-in origin\n", + addr); + } + } + + /* weight */ + if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_WEIGHT)) + if (!peer_group_active(peer) + || !peer_af_flag_check(g_peer, afi, safi, PEER_FLAG_WEIGHT) + || peer->weight[afi][safi] != g_peer->weight[afi][safi]) { + if (peer->weight[afi][safi]) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s weight %lu\n", + addr, + peer->weight[afi][safi]); + } + } + + /* Filter. */ + bgp_config_write_filter(vty, peer, afi, safi, write); + + /* atribute-unchanged. */ + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED) + || CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_NEXTHOP_UNCHANGED) + || CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) { + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_AS_PATH_UNCHANGED) + && peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_NEXTHOP_UNCHANGED) + && peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_MED_UNCHANGED)) { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s attribute-unchanged\n", addr); + } else { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s attribute-unchanged%s%s%s\n", + addr, + peergroup_af_flag_check( + peer, afi, safi, + PEER_FLAG_AS_PATH_UNCHANGED) + ? " as-path" + : "", + peergroup_af_flag_check( + peer, afi, safi, + PEER_FLAG_NEXTHOP_UNCHANGED) + ? " next-hop" + : "", + peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_MED_UNCHANGED) + ? " med" + : ""); + } + } } /* Display "address-family" configuration header. */ -void -bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi, - int *write) -{ - if (*write) - return; - - vty_out (vty, " !\n address-family "); - - if (afi == AFI_IP) - { - if (safi == SAFI_UNICAST) - vty_out (vty, "ipv4 unicast"); - else if (safi == SAFI_LABELED_UNICAST) - vty_out (vty, "ipv4 labeled-unicast"); - else if (safi == SAFI_MULTICAST) - vty_out (vty, "ipv4 multicast"); - else if (safi == SAFI_MPLS_VPN) - vty_out (vty, "ipv4 vpn"); - else if (safi == SAFI_ENCAP) - vty_out (vty, "ipv4 encap"); - } - else if (afi == AFI_IP6) - { - if (safi == SAFI_UNICAST) - vty_out (vty, "ipv6 unicast"); - else if (safi == SAFI_LABELED_UNICAST) - vty_out (vty, "ipv6 labeled-unicast"); - else if (safi == SAFI_MULTICAST) - vty_out (vty, "ipv6 multicast"); - else if (safi == SAFI_MPLS_VPN) - vty_out (vty, "ipv6 vpn"); - else if (safi == SAFI_ENCAP) - vty_out (vty, "ipv6 encap"); - } - else if (afi == AFI_L2VPN) - { - if (safi == SAFI_EVPN) - vty_out (vty, "l2vpn evpn"); - } - vty_out (vty, "\n"); - - *write = 1; +void bgp_config_write_family_header(struct vty *vty, afi_t afi, safi_t safi, + int *write) +{ + if (*write) + return; + + vty_out(vty, " !\n address-family "); + + if (afi == AFI_IP) { + if (safi == SAFI_UNICAST) + vty_out(vty, "ipv4 unicast"); + else if (safi == SAFI_LABELED_UNICAST) + vty_out(vty, "ipv4 labeled-unicast"); + else if (safi == SAFI_MULTICAST) + vty_out(vty, "ipv4 multicast"); + else if (safi == SAFI_MPLS_VPN) + vty_out(vty, "ipv4 vpn"); + else if (safi == SAFI_ENCAP) + vty_out(vty, "ipv4 encap"); + } else if (afi == AFI_IP6) { + if (safi == SAFI_UNICAST) + vty_out(vty, "ipv6 unicast"); + else if (safi == SAFI_LABELED_UNICAST) + vty_out(vty, "ipv6 labeled-unicast"); + else if (safi == SAFI_MULTICAST) + vty_out(vty, "ipv6 multicast"); + else if (safi == SAFI_MPLS_VPN) + vty_out(vty, "ipv6 vpn"); + else if (safi == SAFI_ENCAP) + vty_out(vty, "ipv6 encap"); + } else if (afi == AFI_L2VPN) { + if (safi == SAFI_EVPN) + vty_out(vty, "l2vpn evpn"); + } + vty_out(vty, "\n"); + + *write = 1; } /* Address family based peer configuration display. */ -static int -bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi) +static int bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi) { - int write = 0; - struct peer *peer; - struct peer_group *group; - struct listnode *node, *nnode; + int write = 0; + struct peer *peer; + struct peer_group *group; + struct listnode *node, *nnode; - bgp_config_write_distance (vty, bgp, afi, safi, &write); + bgp_config_write_distance(vty, bgp, afi, safi, &write); - bgp_config_write_network (vty, bgp, afi, safi, &write); + bgp_config_write_network(vty, bgp, afi, safi, &write); - bgp_config_write_redistribute (vty, bgp, afi, safi, &write); + bgp_config_write_redistribute(vty, bgp, afi, safi, &write); - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - bgp_config_write_peer_af (vty, bgp, group->conf, afi, safi, &write); + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) + bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi, + &write); - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - /* Skip dynamic neighbors. */ - if (peer_dynamic_neighbor (peer)) - continue; + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + /* Skip dynamic neighbors. */ + if (peer_dynamic_neighbor(peer)) + continue; - /* Do not display doppelganger peers */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)) - bgp_config_write_peer_af (vty, bgp, peer, afi, safi, &write); - } + /* Do not display doppelganger peers */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + bgp_config_write_peer_af(vty, bgp, peer, afi, safi, + &write); + } - bgp_config_write_maxpaths (vty, bgp, afi, safi, &write); - bgp_config_write_table_map (vty, bgp, afi, safi, &write); + bgp_config_write_maxpaths(vty, bgp, afi, safi, &write); + bgp_config_write_table_map(vty, bgp, afi, safi, &write); - if (safi == SAFI_EVPN) - bgp_config_write_evpn_info (vty, bgp, afi, safi, &write); + if (safi == SAFI_EVPN) + bgp_config_write_evpn_info(vty, bgp, afi, safi, &write); - if (write) - vty_out (vty, " exit-address-family\n"); + if (write) + vty_out(vty, " exit-address-family\n"); - return write; + return write; } -int -bgp_config_write (struct vty *vty) +int bgp_config_write(struct vty *vty) { - int write = 0; - struct bgp *bgp; - struct peer_group *group; - struct peer *peer; - struct listnode *node, *nnode; - struct listnode *mnode, *mnnode; + int write = 0; + struct bgp *bgp; + struct peer_group *group; + struct peer *peer; + struct listnode *node, *nnode; + struct listnode *mnode, *mnnode; - /* BGP Multiple instance. */ - if (!bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE)) - { - vty_out (vty, "no bgp multiple-instance\n"); - write++; - } + /* BGP Multiple instance. */ + if (!bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) { + vty_out(vty, "no bgp multiple-instance\n"); + write++; + } - /* BGP Config type. */ - if (bgp_option_check (BGP_OPT_CONFIG_CISCO)) - { - vty_out (vty, "bgp config-type cisco\n"); - write++; - } + /* BGP Config type. */ + if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) { + vty_out(vty, "bgp config-type cisco\n"); + write++; + } - if (bm->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER) - vty_out (vty, "bgp route-map delay-timer %u\n",bm->rmap_update_timer); + if (bm->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER) + vty_out(vty, "bgp route-map delay-timer %u\n", + bm->rmap_update_timer); + + /* BGP configuration. */ + for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) { + if (write) + vty_out(vty, "!\n"); + + /* Router bgp ASN */ + vty_out(vty, "router bgp %u", bgp->as); + + if (bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) { + if (bgp->name) + vty_out(vty, " %s %s", + (bgp->inst_type + == BGP_INSTANCE_TYPE_VIEW) + ? "view" + : "vrf", + bgp->name); + } + vty_out(vty, "\n"); + + /* No Synchronization */ + if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) + vty_out(vty, " no synchronization\n"); + + /* BGP fast-external-failover. */ + if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER)) + vty_out(vty, " no bgp fast-external-failover\n"); + + /* BGP router ID. */ + if (bgp->router_id_static.s_addr != 0) + vty_out(vty, " bgp router-id %s\n", + inet_ntoa(bgp->router_id_static)); + + /* BGP log-neighbor-changes. */ + if (!!bgp_flag_check(bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES) + != DFLT_BGP_LOG_NEIGHBOR_CHANGES) + vty_out(vty, " %sbgp log-neighbor-changes\n", + bgp_flag_check(bgp, + BGP_FLAG_LOG_NEIGHBOR_CHANGES) + ? "" + : "no "); + + /* BGP configuration. */ + if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED)) + vty_out(vty, " bgp always-compare-med\n"); + + /* BGP default ipv4-unicast. */ + if (bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4)) + vty_out(vty, " no bgp default ipv4-unicast\n"); + + /* BGP default local-preference. */ + if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF) + vty_out(vty, " bgp default local-preference %u\n", + bgp->default_local_pref); + + /* BGP default show-hostname */ + if (!!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME) + != DFLT_BGP_SHOW_HOSTNAME) + vty_out(vty, " %sbgp default show-hostname\n", + bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME) + ? "" + : "no "); + + /* BGP default subgroup-pkt-queue-max. */ + if (bgp->default_subgroup_pkt_queue_max + != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX) + vty_out(vty, " bgp default subgroup-pkt-queue-max %u\n", + bgp->default_subgroup_pkt_queue_max); + + /* BGP client-to-client reflection. */ + if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT)) + vty_out(vty, " no bgp client-to-client reflection\n"); + + /* BGP cluster ID. */ + if (CHECK_FLAG(bgp->config, BGP_CONFIG_CLUSTER_ID)) + vty_out(vty, " bgp cluster-id %s\n", + inet_ntoa(bgp->cluster_id)); + + /* Disable ebgp connected nexthop check */ + if (bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) + vty_out(vty, + " bgp disable-ebgp-connected-route-check\n"); + + /* Confederation identifier*/ + if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) + vty_out(vty, " bgp confederation identifier %i\n", + bgp->confed_id); + + /* Confederation peer */ + if (bgp->confed_peers_cnt > 0) { + int i; + + vty_out(vty, " bgp confederation peers"); + + for (i = 0; i < bgp->confed_peers_cnt; i++) + vty_out(vty, " %u", bgp->confed_peers[i]); + + vty_out(vty, "\n"); + } - /* BGP configuration. */ - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) - { - if (write) - vty_out (vty, "!\n"); + /* BGP enforce-first-as. */ + if (bgp_flag_check(bgp, BGP_FLAG_ENFORCE_FIRST_AS)) + vty_out(vty, " bgp enforce-first-as\n"); + + /* BGP deterministic-med. */ + if (!!bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED) + != DFLT_BGP_DETERMINISTIC_MED) + vty_out(vty, " %sbgp deterministic-med\n", + bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED) + ? "" + : "no "); + + /* BGP update-delay. */ + bgp_config_write_update_delay(vty, bgp); + + if (bgp->v_maxmed_onstartup + != BGP_MAXMED_ONSTARTUP_UNCONFIGURED) { + vty_out(vty, " bgp max-med on-startup %u", + bgp->v_maxmed_onstartup); + if (bgp->maxmed_onstartup_value + != BGP_MAXMED_VALUE_DEFAULT) + vty_out(vty, " %u", + bgp->maxmed_onstartup_value); + vty_out(vty, "\n"); + } + if (bgp->v_maxmed_admin != BGP_MAXMED_ADMIN_UNCONFIGURED) { + vty_out(vty, " bgp max-med administrative"); + if (bgp->maxmed_admin_value != BGP_MAXMED_VALUE_DEFAULT) + vty_out(vty, " %u", bgp->maxmed_admin_value); + vty_out(vty, "\n"); + } - /* Router bgp ASN */ - vty_out (vty, "router bgp %u", bgp->as); + /* write quanta */ + bgp_config_write_wpkt_quanta(vty, bgp); + + /* coalesce time */ + bgp_config_write_coalesce_time(vty, bgp); + + /* BGP graceful-restart. */ + if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME) + vty_out(vty, + " bgp graceful-restart stalepath-time %u\n", + bgp->stalepath_time); + if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME) + vty_out(vty, " bgp graceful-restart restart-time %u\n", + bgp->restart_time); + if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_RESTART)) + vty_out(vty, " bgp graceful-restart\n"); + + /* BGP graceful-restart Preserve State F bit. */ + if (bgp_flag_check(bgp, BGP_FLAG_GR_PRESERVE_FWD)) + vty_out(vty, + " bgp graceful-restart preserve-fw-state\n"); + + /* BGP bestpath method. */ + if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE)) + vty_out(vty, " bgp bestpath as-path ignore\n"); + if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED)) + vty_out(vty, " bgp bestpath as-path confed\n"); + + if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) { + if (bgp_flag_check(bgp, + BGP_FLAG_MULTIPATH_RELAX_AS_SET)) { + vty_out(vty, + " bgp bestpath as-path multipath-relax as-set\n"); + } else { + vty_out(vty, + " bgp bestpath as-path multipath-relax\n"); + } + } - if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE)) - { - if (bgp->name) - vty_out (vty, " %s %s", - (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) ? - "view" : "vrf", bgp->name); - } - vty_out (vty, "\n"); - - /* No Synchronization */ - if (bgp_option_check (BGP_OPT_CONFIG_CISCO)) - vty_out (vty, " no synchronization\n"); - - /* BGP fast-external-failover. */ - if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER)) - vty_out (vty, " no bgp fast-external-failover\n"); - - /* BGP router ID. */ - if (bgp->router_id_static.s_addr != 0) - vty_out (vty, " bgp router-id %s\n", - inet_ntoa(bgp->router_id_static)); - - /* BGP log-neighbor-changes. */ - if (!!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES) - != DFLT_BGP_LOG_NEIGHBOR_CHANGES) - vty_out (vty, " %sbgp log-neighbor-changes\n", - bgp_flag_check(bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES) ? "" : "no "); - - /* BGP configuration. */ - if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED)) - vty_out (vty, " bgp always-compare-med\n"); - - /* BGP default ipv4-unicast. */ - if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)) - vty_out (vty, " no bgp default ipv4-unicast\n"); - - /* BGP default local-preference. */ - if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF) - vty_out (vty, " bgp default local-preference %u\n", - bgp->default_local_pref); - - /* BGP default show-hostname */ - if (!!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME) - != DFLT_BGP_SHOW_HOSTNAME) - vty_out (vty, " %sbgp default show-hostname\n", - bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME) ? "" : "no "); - - /* BGP default subgroup-pkt-queue-max. */ - if (bgp->default_subgroup_pkt_queue_max != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX) - vty_out (vty, " bgp default subgroup-pkt-queue-max %u\n", - bgp->default_subgroup_pkt_queue_max); - - /* BGP client-to-client reflection. */ - if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT)) - vty_out (vty, " no bgp client-to-client reflection\n"); - - /* BGP cluster ID. */ - if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID)) - vty_out (vty, " bgp cluster-id %s\n",inet_ntoa(bgp->cluster_id)); - - /* Disable ebgp connected nexthop check */ - if (bgp_flag_check (bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) - vty_out (vty, " bgp disable-ebgp-connected-route-check\n"); - - /* Confederation identifier*/ - if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION)) - vty_out (vty, " bgp confederation identifier %i\n",bgp->confed_id); - - /* Confederation peer */ - if (bgp->confed_peers_cnt > 0) - { - int i; - - vty_out (vty, " bgp confederation peers"); - - for (i = 0; i < bgp->confed_peers_cnt; i++) - vty_out(vty, " %u", bgp->confed_peers[i]); - - vty_out (vty, "\n"); - } - - /* BGP enforce-first-as. */ - if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS)) - vty_out (vty, " bgp enforce-first-as\n"); - - /* BGP deterministic-med. */ - if (!!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED) - != DFLT_BGP_DETERMINISTIC_MED) - vty_out (vty, " %sbgp deterministic-med\n", - bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED) ? "" : "no "); - - /* BGP update-delay. */ - bgp_config_write_update_delay (vty, bgp); - - if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED) - { - vty_out (vty, " bgp max-med on-startup %u", bgp->v_maxmed_onstartup); - if (bgp->maxmed_onstartup_value != BGP_MAXMED_VALUE_DEFAULT) - vty_out (vty, " %u", bgp->maxmed_onstartup_value); - vty_out (vty, "\n"); - } - if (bgp->v_maxmed_admin != BGP_MAXMED_ADMIN_UNCONFIGURED) - { - vty_out (vty, " bgp max-med administrative"); - if (bgp->maxmed_admin_value != BGP_MAXMED_VALUE_DEFAULT) - vty_out (vty, " %u", bgp->maxmed_admin_value); - vty_out (vty, "\n"); - } - - /* write quanta */ - bgp_config_write_wpkt_quanta (vty, bgp); - - /* coalesce time */ - bgp_config_write_coalesce_time(vty, bgp); - - /* BGP graceful-restart. */ - if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME) - vty_out (vty, " bgp graceful-restart stalepath-time %u\n", - bgp->stalepath_time); - if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME) - vty_out (vty, " bgp graceful-restart restart-time %u\n", - bgp->restart_time); - if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART)) - vty_out (vty, " bgp graceful-restart\n"); - - /* BGP graceful-restart Preserve State F bit. */ - if (bgp_flag_check (bgp, BGP_FLAG_GR_PRESERVE_FWD)) - vty_out (vty, " bgp graceful-restart preserve-fw-state\n"); - - /* BGP bestpath method. */ - if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE)) - vty_out (vty, " bgp bestpath as-path ignore\n"); - if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED)) - vty_out (vty, " bgp bestpath as-path confed\n"); - - if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) - { - if (bgp_flag_check (bgp, BGP_FLAG_MULTIPATH_RELAX_AS_SET)) - { - vty_out (vty, - " bgp bestpath as-path multipath-relax as-set\n"); - } - else - { - vty_out (vty, " bgp bestpath as-path multipath-relax\n"); - } - } - - if (bgp_flag_check (bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) { - vty_out (vty," bgp route-reflector allow-outbound-policy\n"); - } - if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID)) - vty_out (vty, " bgp bestpath compare-routerid\n"); - if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED) - || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST)) - { - vty_out (vty, " bgp bestpath med"); - if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)) - vty_out (vty, " confed"); - if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST)) - vty_out (vty, " missing-as-worst"); - vty_out (vty, "\n"); - } - - /* BGP network import check. */ - if (!!bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK) - != DFLT_BGP_IMPORT_CHECK) - vty_out (vty, " %sbgp network import-check\n", - bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK) ? "" : "no "); - - /* BGP flag dampening. */ - if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST], - BGP_CONFIG_DAMPENING)) - bgp_config_write_damp (vty); - - /* BGP timers configuration. */ - if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE - && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME) - vty_out (vty, " timers bgp %u %u\n", bgp->default_keepalive, - bgp->default_holdtime); - - /* peer-group */ - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - { - bgp_config_write_peer_global (vty, bgp, group->conf); - } + if (bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) { + vty_out(vty, + " bgp route-reflector allow-outbound-policy\n"); + } + if (bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID)) + vty_out(vty, " bgp bestpath compare-routerid\n"); + if (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED) + || bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST)) { + vty_out(vty, " bgp bestpath med"); + if (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED)) + vty_out(vty, " confed"); + if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST)) + vty_out(vty, " missing-as-worst"); + vty_out(vty, "\n"); + } - /* Normal neighbor configuration. */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)) - bgp_config_write_peer_global (vty, bgp, peer); - } + /* BGP network import check. */ + if (!!bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK) + != DFLT_BGP_IMPORT_CHECK) + vty_out(vty, " %sbgp network import-check\n", + bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK) + ? "" + : "no "); + + /* BGP flag dampening. */ + if (CHECK_FLAG(bgp->af_flags[AFI_IP][SAFI_UNICAST], + BGP_CONFIG_DAMPENING)) + bgp_config_write_damp(vty); + + /* BGP timers configuration. */ + if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE + && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME) + vty_out(vty, " timers bgp %u %u\n", + bgp->default_keepalive, bgp->default_holdtime); + + /* peer-group */ + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) { + bgp_config_write_peer_global(vty, bgp, group->conf); + } + + /* Normal neighbor configuration. */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + bgp_config_write_peer_global(vty, bgp, peer); + } - /* listen range and limit for dynamic BGP neighbors */ - bgp_config_write_listen (vty, bgp); + /* listen range and limit for dynamic BGP neighbors */ + bgp_config_write_listen(vty, bgp); - /* No auto-summary */ - if (bgp_option_check (BGP_OPT_CONFIG_CISCO)) - vty_out (vty, " no auto-summary\n"); + /* No auto-summary */ + if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) + vty_out(vty, " no auto-summary\n"); - /* IPv4 unicast configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_UNICAST); + /* IPv4 unicast configuration. */ + write += + bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST); - /* IPv4 multicast configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST); + /* IPv4 multicast configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP, + SAFI_MULTICAST); - /* IPv4 labeled-unicast configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_LABELED_UNICAST); + /* IPv4 labeled-unicast configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP, + SAFI_LABELED_UNICAST); - /* IPv4 VPN configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN); + /* IPv4 VPN configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP, + SAFI_MPLS_VPN); - /* ENCAPv4 configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_ENCAP); + /* ENCAPv4 configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP, SAFI_ENCAP); - /* IPv6 unicast configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST); + /* IPv6 unicast configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP6, + SAFI_UNICAST); - /* IPv6 multicast configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST); + /* IPv6 multicast configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP6, + SAFI_MULTICAST); - /* IPv6 labeled-unicast configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_LABELED_UNICAST); + /* IPv6 labeled-unicast configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP6, + SAFI_LABELED_UNICAST); - /* IPv6 VPN configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MPLS_VPN); + /* IPv6 VPN configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP6, + SAFI_MPLS_VPN); - /* ENCAPv6 configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP); + /* ENCAPv6 configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_ENCAP); - /* EVPN configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_L2VPN, SAFI_EVPN); + /* EVPN configuration. */ + write += + bgp_config_write_family(vty, bgp, AFI_L2VPN, SAFI_EVPN); #if ENABLE_BGP_VNC - write += bgp_rfapi_cfg_write(vty, bgp); + write += bgp_rfapi_cfg_write(vty, bgp); #endif - write++; - } - return write; + write++; + } + return write; } -void -bgp_master_init (struct thread_master *master) +void bgp_master_init(struct thread_master *master) { - qobj_init (); + qobj_init(); - memset (&bgp_master, 0, sizeof (struct bgp_master)); + memset(&bgp_master, 0, sizeof(struct bgp_master)); - bm = &bgp_master; - bm->bgp = list_new (); - bm->listen_sockets = list_new (); - bm->port = BGP_PORT_DEFAULT; - bm->master = master; - bm->start_time = bgp_clock (); - bm->t_rmap_update = NULL; - bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER; + bm = &bgp_master; + bm->bgp = list_new(); + bm->listen_sockets = list_new(); + bm->port = BGP_PORT_DEFAULT; + bm->master = master; + bm->start_time = bgp_clock(); + bm->t_rmap_update = NULL; + bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER; - bgp_process_queue_init(); + bgp_process_queue_init(); - /* Enable multiple instances by default. */ - bgp_option_set (BGP_OPT_MULTIPLE_INSTANCE); + /* Enable multiple instances by default. */ + bgp_option_set(BGP_OPT_MULTIPLE_INSTANCE); - QOBJ_REG (bm, bgp_master); + QOBJ_REG(bm, bgp_master); } /* * Free up connected routes and interfaces for a BGP instance. Invoked upon * instance delete (non-default only) or BGP exit. */ -static void -bgp_if_finish (struct bgp *bgp) +static void bgp_if_finish(struct bgp *bgp) { - struct listnode *ifnode, *ifnnode; - struct interface *ifp; - - if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) - return; + struct listnode *ifnode, *ifnnode; + struct interface *ifp; + + if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) + return; - for (ALL_LIST_ELEMENTS (vrf_iflist(bgp->vrf_id), ifnode, ifnnode, ifp)) - { - struct listnode *c_node, *c_nnode; - struct connected *c; + for (ALL_LIST_ELEMENTS(vrf_iflist(bgp->vrf_id), ifnode, ifnnode, ifp)) { + struct listnode *c_node, *c_nnode; + struct connected *c; - for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c)) - bgp_connected_delete (bgp, c); - } + for (ALL_LIST_ELEMENTS(ifp->connected, c_node, c_nnode, c)) + bgp_connected_delete(bgp, c); + } } -extern void bgp_snmp_init (void); +extern void bgp_snmp_init(void); -static void -bgp_viewvrf_autocomplete (vector comps, struct cmd_token *token) +static void bgp_viewvrf_autocomplete(vector comps, struct cmd_token *token) { - struct vrf *vrf = NULL; - struct listnode *next; - struct bgp *bgp; + struct vrf *vrf = NULL; + struct listnode *next; + struct bgp *bgp; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if (vrf->vrf_id != VRF_DEFAULT) - vector_set (comps, XSTRDUP (MTYPE_COMPLETION, vrf->name)); - } + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if (vrf->vrf_id != VRF_DEFAULT) + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name)); + } - for (ALL_LIST_ELEMENTS_RO (bm->bgp, next, bgp)) - { - if (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) - continue; + for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) { + if (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) + continue; - vector_set (comps, XSTRDUP (MTYPE_COMPLETION, bgp->name)); - } + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, bgp->name)); + } } static const struct cmd_variable_handler bgp_viewvrf_var_handlers[] = { - { - .tokenname = "VIEWVRFNAME", - .completions = bgp_viewvrf_autocomplete - }, - { - .completions = NULL - }, + {.tokenname = "VIEWVRFNAME", .completions = bgp_viewvrf_autocomplete}, + {.completions = NULL}, }; -void -bgp_init (void) +void bgp_init(void) { - /* allocates some vital data structures used by peer commands in vty_init */ + /* allocates some vital data structures used by peer commands in + * vty_init */ - /* Init zebra. */ - bgp_zebra_init(bm->master); + /* Init zebra. */ + bgp_zebra_init(bm->master); #if ENABLE_BGP_VNC - vnc_zebra_init (bm->master); + vnc_zebra_init(bm->master); #endif - /* BGP VTY commands installation. */ - bgp_vty_init (); - - /* BGP inits. */ - bgp_attr_init (); - bgp_debug_init (); - bgp_dump_init (); - bgp_route_init (); - bgp_route_map_init (); - bgp_scan_vty_init(); - bgp_mplsvpn_init (); + /* BGP VTY commands installation. */ + bgp_vty_init(); + + /* BGP inits. */ + bgp_attr_init(); + bgp_debug_init(); + bgp_dump_init(); + bgp_route_init(); + bgp_route_map_init(); + bgp_scan_vty_init(); + bgp_mplsvpn_init(); #if ENABLE_BGP_VNC - rfapi_init (); + rfapi_init(); #endif - bgp_ethernetvpn_init (); - - /* Access list initialize. */ - access_list_init (); - access_list_add_hook (peer_distribute_update); - access_list_delete_hook (peer_distribute_update); - - /* Filter list initialize. */ - bgp_filter_init (); - as_list_add_hook (peer_aslist_add); - as_list_delete_hook (peer_aslist_del); - - /* Prefix list initialize.*/ - prefix_list_init (); - prefix_list_add_hook (peer_prefix_list_update); - prefix_list_delete_hook (peer_prefix_list_update); - - /* Community list initialize. */ - bgp_clist = community_list_init (); - - /* BFD init */ - bgp_bfd_init(); - - cmd_variable_handler_register (bgp_viewvrf_var_handlers); -} - -void -bgp_terminate (void) -{ - struct bgp *bgp; - struct peer *peer; - struct listnode *node, *nnode; - struct listnode *mnode, *mnnode; - - QOBJ_UNREG (bm); - - /* Close the listener sockets first as this prevents peers from attempting - * to reconnect on receiving the peer unconfig message. In the presence - * of a large number of peers this will ensure that no peer is left with - * a dangling connection - */ - /* reverse bgp_master_init */ - bgp_close(); - if (bm->listen_sockets) - list_free(bm->listen_sockets); - bm->listen_sockets = NULL; - - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - if (peer->status == Established || - peer->status == OpenSent || - peer->status == OpenConfirm) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_PEER_UNCONFIG); - - if (bm->process_main_queue) - { - work_queue_free (bm->process_main_queue); - bm->process_main_queue = NULL; - } - - if (bm->t_rmap_update) - BGP_TIMER_OFF(bm->t_rmap_update); + bgp_ethernetvpn_init(); + + /* Access list initialize. */ + access_list_init(); + access_list_add_hook(peer_distribute_update); + access_list_delete_hook(peer_distribute_update); + + /* Filter list initialize. */ + bgp_filter_init(); + as_list_add_hook(peer_aslist_add); + as_list_delete_hook(peer_aslist_del); + + /* Prefix list initialize.*/ + prefix_list_init(); + prefix_list_add_hook(peer_prefix_list_update); + prefix_list_delete_hook(peer_prefix_list_update); + + /* Community list initialize. */ + bgp_clist = community_list_init(); + + /* BFD init */ + bgp_bfd_init(); + + cmd_variable_handler_register(bgp_viewvrf_var_handlers); +} + +void bgp_terminate(void) +{ + struct bgp *bgp; + struct peer *peer; + struct listnode *node, *nnode; + struct listnode *mnode, *mnnode; + + QOBJ_UNREG(bm); + + /* Close the listener sockets first as this prevents peers from + * attempting + * to reconnect on receiving the peer unconfig message. In the presence + * of a large number of peers this will ensure that no peer is left with + * a dangling connection + */ + /* reverse bgp_master_init */ + bgp_close(); + if (bm->listen_sockets) + list_free(bm->listen_sockets); + bm->listen_sockets = NULL; + + for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) + if (peer->status == Established + || peer->status == OpenSent + || peer->status == OpenConfirm) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_PEER_UNCONFIG); + + if (bm->process_main_queue) { + work_queue_free(bm->process_main_queue); + bm->process_main_queue = NULL; + } + + if (bm->t_rmap_update) + BGP_TIMER_OFF(bm->t_rmap_update); } |
