diff options
Diffstat (limited to 'bgpd/bgpd.c')
-rw-r--r-- | bgpd/bgpd.c | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 128bfef1..c4e54f03 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -788,6 +788,7 @@ peer_new (struct bgp *bgp) peer->status = Idle; peer->ostatus = Idle; peer->weight = 0; + peer->password = NULL; peer->bgp = bgp; peer = peer_lock (peer); /* initial reference */ @@ -1202,6 +1203,20 @@ peer_delete (struct peer *peer) peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE; bgp_stop (peer); bgp_fsm_change_status (peer, Deleted); + +#ifdef HAVE_TCP_MD5SIG + /* Password configuration */ + if (peer->password) + { + free (peer->password); + peer->password = NULL; + + if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP) + && sockunion_family (&peer->su) == AF_INET) + bgp_md5_set (bm->sock, &peer->su.sin, NULL); + } +#endif /* HAVE_TCP_MD5SIG */ + bgp_timer_set (peer); /* stops all timers for Deleted */ /* Delete from all peer list. */ @@ -1417,6 +1432,27 @@ peer_group2peer_config_copy (struct peer_group *group, struct peer *peer, else peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; +#ifdef HAVE_TCP_MD5SIG + /* password apply */ + if (CHECK_FLAG (conf->flags, PEER_FLAG_PASSWORD)) + { + if (peer->password) + free (peer->password); + peer->password = strdup (conf->password); + + if (sockunion_family (&peer->su) == AF_INET) + bgp_md5_set (bm->sock, &peer->su.sin, peer->password); + } + else if (peer->password) + { + free (peer->password); + peer->password = NULL; + + if (sockunion_family (&peer->su) == AF_INET) + bgp_md5_set (bm->sock, &peer->su.sin, NULL); + } +#endif /* HAVE_TCP_MD5SIG */ + /* maximum-prefix */ peer->pmax[afi][safi] = conf->pmax[afi][safi]; peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi]; @@ -3379,6 +3415,125 @@ peer_local_as_unset (struct peer *peer) return 0; } +#ifdef HAVE_TCP_MD5SIG +/* Set password for authenticating with the peer. */ +int +peer_password_set (struct peer *peer, const char *password) +{ + struct peer_group *group; + struct listnode *nn, *nnode; + int len = password ? strlen(password) : 0; + + 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; + + SET_FLAG (peer->flags, PEER_FLAG_PASSWORD); + if (peer->password) + free (peer->password); + peer->password = strdup (password); + + if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) + { + if (peer->status == Established) + bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + BGP_EVENT_ADD (peer, BGP_Stop); + + if (sockunion_family (&peer->su) == AF_INET) + bgp_md5_set (bm->sock, &peer->su.sin, peer->password); + return 0; + } + + group = peer->group; + /* #42# LIST_LOOP (group->peer, peer, nn) */ + for (ALL_LIST_ELEMENTS (group->peer, nn, nnode, peer)) + { + if (peer->password && strcmp (peer->password, password) == 0) + continue; + + SET_FLAG (peer->flags, PEER_FLAG_PASSWORD); + if (peer->password) + free (peer->password); + peer->password = strdup (password); + + if (peer->status == Established) + bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + BGP_EVENT_ADD (peer, BGP_Stop); + + if (sockunion_family (&peer->su) == AF_INET) + bgp_md5_set (bm->sock, &peer->su.sin, peer->password); + } + + return 0; +} + +int +peer_password_unset (struct peer *peer) +{ + struct peer_group *group; + struct listnode *nn, *nnode; + + if (! CHECK_FLAG (peer->flags, PEER_FLAG_PASSWORD) + && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) + return 0; + + if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) + { + if (peer_group_active (peer) + && CHECK_FLAG (peer->group->conf->flags, PEER_FLAG_PASSWORD)) + return BGP_ERR_PEER_GROUP_HAS_THE_FLAG; + + if (peer->status == Established) + bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + BGP_EVENT_ADD (peer, BGP_Stop); + + if (sockunion_family (&peer->su) == AF_INET) + bgp_md5_set (bm->sock, &peer->su.sin, NULL); + + UNSET_FLAG (peer->flags, PEER_FLAG_PASSWORD); + if (peer->password) + free (peer->password); + peer->password = NULL; + + return 0; + } + + UNSET_FLAG (peer->flags, PEER_FLAG_PASSWORD); + if (peer->password) + free (peer->password); + peer->password = NULL; + + group = peer->group; + /* #42# LIST_LOOP (group->peer, peer, nn) */ + for (ALL_LIST_ELEMENTS (group->peer, nn, nnode, peer)) + { + if (! CHECK_FLAG (peer->flags, PEER_FLAG_PASSWORD)) + continue; + + if (peer->status == Established) + bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + BGP_EVENT_ADD (peer, BGP_Stop); + + if (sockunion_family (&peer->su) == AF_INET) + bgp_md5_set (bm->sock, &peer->su.sin, NULL); + + UNSET_FLAG (peer->flags, PEER_FLAG_PASSWORD); + if (peer->password) + free (peer->password); + peer->password = NULL; + } + + return 0; +} +#endif /* HAVE_TCP_MD5SIG */ + /* Set distribute list to the peer. */ int peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct, @@ -4416,6 +4571,16 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp, ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN)) vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE); +#ifdef HAVE_TCP_MD5SIG + /* Password. */ + if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSWORD)) + if (! peer_group_active (peer) + || ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSWORD) + || strcmp (peer->password, g_peer->password) != 0) + vty_out (vty, " neighbor %s password %s%s", addr, peer->password, + VTY_NEWLINE); +#endif /* HAVE_TCP_MD5SIG */ + /* BGP port. */ if (peer->port != BGP_PORT_DEFAULT) vty_out (vty, " neighbor %s port %d%s", addr, peer->port, @@ -4951,6 +5116,9 @@ bgp_master_init (void) bm->port = BGP_PORT_DEFAULT; bm->master = thread_master_create (); bm->start_time = time (NULL); +#ifdef HAVE_TCP_MD5SIG + bm->sock = -1; +#endif /* HAVE_TCP_MD5SIG */ } |