From bd838d8c896140ae43b41bb7f8fcf88a26ec5a0f Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Wed, 7 Dec 2022 10:13:39 -0300 Subject: [PATCH] pimd: add support for MSDP authentication Implement MSDP MD5 authentication connection support. Implementation details: - Move the MSDP socket creation code to a generic function so it can be parametrized to be used with/without authentication. - The MSDP peer connection will not change when the configuration is set, instead it will only be applied next connection or when `clear ip msdp peer A.B.C.D` is called. Signed-off-by: Rafael Zalamena --- pimd/pim_cmd.c | 87 +++++++++++++ pimd/pim_memory.c | 1 + pimd/pim_memory.h | 1 + pimd/pim_msdp.c | 37 +++++- pimd/pim_msdp.h | 21 ++++ pimd/pim_msdp_socket.c | 280 +++++++++++++++++++++++++++++++---------- pimd/pim_msdp_socket.h | 3 + pimd/pim_nb.c | 13 ++ pimd/pim_nb.h | 3 + pimd/pim_nb_config.c | 79 ++++++++++++ 10 files changed, 457 insertions(+), 68 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 1e3e090868..dcfad2a4f8 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2823,6 +2823,39 @@ DEFPY (clear_ip_mroute_count, return clear_ip_mroute_count_command(vty, name); } +DEFPY(clear_ip_msdp_peer, clear_ip_msdp_peer_cmd, + "clear ip msdp peer A.B.C.D$peer [vrf WORD$vrfname]", + CLEAR_STR + IP_STR + MSDP_STR + "Restart MSDP peer\n" + "MSDP peer address\n" + VRF_CMD_HELP_STR) +{ + const struct pim_instance *pim; + const struct listnode *node; + const struct vrf *vrf; + struct pim_msdp_peer *mp; + + if (vrfname) { + vrf = vrf_lookup_by_name(vrfname); + if (vrf == NULL) + return CMD_WARNING; + } else + vrf = vrf_lookup_by_id(VRF_DEFAULT); + + pim = vrf->info; + for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, node, mp)) { + if (mp->peer.s_addr != peer.s_addr) + continue; + + pim_msdp_peer_restart(mp); + break; + } + + return CMD_SUCCESS; +} + DEFPY (show_ip_mroute_count, show_ip_mroute_count_cmd, "show ip mroute [vrf NAME] count [json$json]", @@ -6285,6 +6318,57 @@ DEFPY_ATTR(ip_pim_msdp_peer, return ret; } +DEFPY(msdp_peer_md5, msdp_peer_md5_cmd, + "msdp peer A.B.C.D$peer password WORD$psk", + CFG_MSDP_STR + "Configure MSDP peer\n" + "MSDP Peer address\n" + "Use MD5 authentication\n" + "MD5 pre shared key\n") +{ + const struct lyd_node *peer_node; + char xpath[XPATH_MAXLEN + 24]; + + snprintf(xpath, sizeof(xpath), "%s/msdp-peer[peer-ip='%s']", + VTY_CURR_XPATH, peer_str); + peer_node = yang_dnode_get(vty->candidate_config->dnode, xpath); + if (peer_node == NULL) { + vty_out(vty, "%% MSDP peer %s not yet configured\n", peer_str); + return CMD_SUCCESS; + } + + nb_cli_enqueue_change(vty, "./authentication-type", NB_OP_MODIFY, "MD5"); + nb_cli_enqueue_change(vty, "./authentication-key", NB_OP_MODIFY, psk); + + return nb_cli_apply_changes(vty, "%s", xpath); +} + +DEFPY(no_msdp_peer_md5, no_msdp_peer_md5_cmd, + "no msdp peer A.B.C.D$peer password [WORD]", + NO_STR + CFG_MSDP_STR + "Configure MSDP peer\n" + "MSDP Peer address\n" + "Use MD5 authentication\n" + "MD5 pre shared key\n") +{ + const struct lyd_node *peer_node; + char xpath[XPATH_MAXLEN + 24]; + + snprintf(xpath, sizeof(xpath), "%s/msdp-peer[peer-ip='%s']", + VTY_CURR_XPATH, peer_str); + peer_node = yang_dnode_get(vty->candidate_config->dnode, xpath); + if (peer_node == NULL) { + vty_out(vty, "%% MSDP peer %s not yet configured\n", peer_str); + return CMD_SUCCESS; + } + + nb_cli_enqueue_change(vty, "./authentication-type", NB_OP_MODIFY, + "None"); + + return nb_cli_apply_changes(vty, "%s", xpath); +} + DEFPY(pim_msdp_timers, pim_msdp_timers_cmd, "msdp timers (1-65535)$keepalive (1-65535)$holdtime [(1-65535)$connretry]", CFG_MSDP_STR @@ -8320,6 +8404,8 @@ void pim_cmd_init(void) install_element(PIM_NODE, &pim_msdp_peer_cmd); install_element(PIM_NODE, &no_pim_msdp_peer_cmd); + install_element(PIM_NODE, &msdp_peer_md5_cmd); + install_element(PIM_NODE, &no_msdp_peer_md5_cmd); install_element(PIM_NODE, &pim_msdp_timers_cmd); install_element(PIM_NODE, &no_pim_msdp_timers_cmd); install_element(PIM_NODE, &msdp_peer_sa_filter_cmd); @@ -8462,6 +8548,7 @@ void pim_cmd_init(void) install_element(ENABLE_NODE, &pim_test_sg_keepalive_cmd); install_element(ENABLE_NODE, &clear_ip_mroute_count_cmd); + install_element(ENABLE_NODE, &clear_ip_msdp_peer_cmd); install_element(ENABLE_NODE, &clear_ip_interfaces_cmd); install_element(ENABLE_NODE, &clear_ip_igmp_interfaces_cmd); install_element(ENABLE_NODE, &clear_ip_mroute_cmd); diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c index 85780f013b..604e24482d 100644 --- a/pimd/pim_memory.c +++ b/pimd/pim_memory.c @@ -26,6 +26,7 @@ DEFINE_MTYPE(PIMD, PIM_RP, "PIM RP info"); DEFINE_MTYPE(PIMD, PIM_FILTER_NAME, "PIM RP filter info"); DEFINE_MTYPE(PIMD, PIM_MSDP_PEER, "PIM MSDP peer"); DEFINE_MTYPE(PIMD, PIM_MSDP_MG_NAME, "PIM MSDP mesh-group name"); +DEFINE_MTYPE(PIMD, PIM_MSDP_AUTH_KEY, "PIM MSDP authentication key"); DEFINE_MTYPE(PIMD, PIM_MSDP_SA, "PIM MSDP source-active cache"); DEFINE_MTYPE(PIMD, PIM_MSDP_MG, "PIM MSDP mesh group"); DEFINE_MTYPE(PIMD, PIM_MSDP_MG_MBR, "PIM MSDP mesh group mbr"); diff --git a/pimd/pim_memory.h b/pimd/pim_memory.h index 41730e7522..353e09a71c 100644 --- a/pimd/pim_memory.h +++ b/pimd/pim_memory.h @@ -28,6 +28,7 @@ DECLARE_MTYPE(PIM_MSDP_MG_NAME); DECLARE_MTYPE(PIM_MSDP_SA); DECLARE_MTYPE(PIM_MSDP_MG); DECLARE_MTYPE(PIM_MSDP_MG_MBR); +DECLARE_MTYPE(PIM_MSDP_AUTH_KEY); DECLARE_MTYPE(PIM_SEC_ADDR); DECLARE_MTYPE(PIM_JP_AGG_GROUP); DECLARE_MTYPE(PIM_JP_AGG_SOURCE); diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 0bb2d93a3a..215cc3c502 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -773,7 +773,10 @@ static void pim_msdp_peer_listen(struct pim_msdp_peer *mp) * first listening peer is configured; but don't bother tearing it down * when * all the peers go down */ - pim_msdp_sock_listen(mp->pim); + if (mp->auth_type == MSDP_AUTH_NONE) + pim_msdp_sock_listen(mp->pim); + else + pim_msdp_sock_auth_listen(mp); } /* 11.2.A4 and 11.2.A5: transition active or passive peer to @@ -1045,6 +1048,7 @@ struct pim_msdp_peer *pim_msdp_peer_add(struct pim_instance *pim, mp->state = PIM_MSDP_INACTIVE; mp->fd = -1; + mp->auth_listen_sock = -1; strlcpy(mp->last_reset, "-", sizeof(mp->last_reset)); /* higher IP address is listener */ if (ntohl(mp->local.s_addr) > ntohl(mp->peer.s_addr)) { @@ -1100,6 +1104,12 @@ static void pim_msdp_peer_free(struct pim_msdp_peer *mp) stream_fifo_free(mp->obuf); } + /* Free authentication data. */ + event_cancel(&mp->auth_listen_ev); + XFREE(MTYPE_PIM_MSDP_AUTH_KEY, mp->auth_key); + if (mp->auth_listen_sock != -1) + close(mp->auth_listen_sock); + XFREE(MTYPE_PIM_MSDP_MG_NAME, mp->mesh_group_name); mp->pim = NULL; @@ -1128,19 +1138,32 @@ void pim_msdp_peer_del(struct pim_msdp_peer **mp) *mp = NULL; } -void pim_msdp_peer_change_source(struct pim_msdp_peer *mp, - const struct in_addr *addr) +void pim_msdp_peer_restart(struct pim_msdp_peer *mp) { + /* Stop auth listening socket if any. */ + event_cancel(&mp->auth_listen_ev); + if (mp->auth_listen_sock != -1) { + close(mp->auth_listen_sock); + mp->auth_listen_sock = -1; + } + + /* Stop previously running connection. */ pim_msdp_peer_stop_tcp_conn(mp, true); - mp->local = *addr; - + /* Start connection again. */ if (PIM_MSDP_PEER_IS_LISTENER(mp)) pim_msdp_peer_listen(mp); else pim_msdp_peer_connect(mp); } +void pim_msdp_peer_change_source(struct pim_msdp_peer *mp, + const struct in_addr *addr) +{ + mp->local = *addr; + pim_msdp_peer_restart(mp); +} + /* peer hash and peer list helpers */ static unsigned int pim_msdp_peer_hash_key_make(const void *p) { @@ -1318,6 +1341,10 @@ bool pim_msdp_peer_config_write(struct vty *vty, struct pim_instance *pim) vty_out(vty, " msdp peer %pI4 source %pI4\n", &mp->peer, &mp->local); + if (mp->auth_type == MSDP_AUTH_MD5) + vty_out(vty, " msdp peer %pI4 password %s\n", &mp->peer, + mp->auth_key); + if (mp->acl_in) vty_out(vty, " msdp peer %pI4 sa-filter %s in\n", &mp->peer, mp->acl_in); diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h index a45726cb85..f77b0e1a3a 100644 --- a/pimd/pim_msdp.h +++ b/pimd/pim_msdp.h @@ -89,6 +89,11 @@ enum pim_msdp_peer_flags { PIM_MSDP_PEERF_IN_GROUP = (1 << 2), }; +enum msdp_auth_type { + MSDP_AUTH_NONE = 0, + MSDP_AUTH_MD5 = 1, +}; + struct pim_msdp_peer { struct pim_instance *pim; @@ -98,6 +103,13 @@ struct pim_msdp_peer { char *mesh_group_name; char key_str[INET_ADDRSTRLEN]; + /* Authentication data. */ + enum msdp_auth_type auth_type; + char *auth_key; + + int auth_listen_sock; + struct event *auth_listen_ev; + /* state */ enum pim_msdp_peer_state state; enum pim_msdp_peer_flags flags; @@ -309,6 +321,15 @@ void pim_msdp_peer_del(struct pim_msdp_peer **mp); void pim_msdp_peer_change_source(struct pim_msdp_peer *mp, const struct in_addr *addr); +/** + * Restart peer's connection. + * + * This is used internally in MSDP and should be used by northbound + * when wanting to immediately apply connections settings such as + * authentication. + */ +void pim_msdp_peer_restart(struct pim_msdp_peer *mp); + #else /* PIM_IPV == 6 */ static inline void pim_msdp_init(struct pim_instance *pim, struct event_loop *master) diff --git a/pimd/pim_msdp_socket.c b/pimd/pim_msdp_socket.c index fe8d5e934a..2fb0bb87c7 100644 --- a/pimd/pim_msdp_socket.c +++ b/pimd/pim_msdp_socket.c @@ -49,6 +49,192 @@ static void pim_msdp_update_sock_send_buffer_size(int fd) } } +/** + * Helper function to reduce code duplication. + * + * \param vrf VRF pointer (`NULL` means default VRF) + * \param mp the MSDP session pointer. + * \returns valid file descriptor otherwise `-1`. + */ +static int _pim_msdp_sock_listen(const struct vrf *vrf, + const struct pim_msdp_peer *mp) +{ + const struct interface *ifp; + int sock; + int rv; + socklen_t socklen; + struct sockaddr_in sin = {}; + union sockunion su_peer = {}; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock == -1) { + zlog_warn("%s: socket: %s", __func__, strerror(errno)); + return -1; + } + + socklen = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(PIM_MSDP_TCP_PORT); +#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN + sin.sin_len = socklen; +#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ + if (mp) + sin.sin_addr = mp->local; + + sockopt_reuseaddr(sock); + sockopt_reuseport(sock); + + /* Bind socket to VRF/address. */ + if (vrf && vrf->vrf_id != VRF_DEFAULT) { + ifp = if_lookup_by_name(vrf->name, vrf->vrf_id); + if (ifp == NULL) { + flog_err(EC_LIB_INTERFACE, + "%s: Unable to lookup vrf interface: %s", + __func__, vrf->name); + close(sock); + return -1; + } + + if (vrf_bind(vrf->vrf_id, sock, ifp->name) == -1) { + flog_err_sys(EC_LIB_SOCKET, + "%s: Unable to bind to socket: %s", + __func__, safe_strerror(errno)); + close(sock); + return -1; + } + } + + frr_with_privs (&pimd_privs) { + rv = bind(sock, (struct sockaddr *)&sin, socklen); + } + if (rv == -1) { + flog_err_sys(EC_LIB_SOCKET, + "pim_msdp_socket bind to port %d: %s", + ntohs(sin.sin_port), safe_strerror(errno)); + close(sock); + return -1; + } + + /* Set MD5 authentication. */ + if (mp && mp->auth_key) { + su_peer = mp->su_peer; + frr_with_privs (&pimd_privs) { + sockopt_tcp_signature(sock, &su_peer, mp->auth_key); + } + } + + + /* Start listening. */ + rv = listen(sock, SOMAXCONN); + if (rv == -1) { + flog_err_sys(EC_LIB_SOCKET, "pim_msdp_socket listen: %s", + safe_strerror(errno)); + close(sock); + return -1; + } + + /* Set socket DSCP byte */ + if (setsockopt_ipv4_tos(sock, IPTOS_PREC_INTERNETCONTROL)) { + zlog_warn("can't set sockopt IP_TOS to MSDP socket %d: %s", + sock, safe_strerror(errno)); + } + + return sock; +} + +static void pim_msdp_sock_auth_accept(struct event *t) +{ + struct pim_msdp_peer *mp = EVENT_ARG(t); + int sock; + socklen_t sinlen; + struct sockaddr_in sin = {}; + + /* accept client connection. */ + sinlen = sizeof(sin); + sock = accept(mp->auth_listen_sock, (struct sockaddr *)&sin, &sinlen); + if (sock == -1) { + flog_err_sys(EC_LIB_SOCKET, "pim_msdp_sock_accept failed (%s)", + safe_strerror(errno)); + + /* Accept failed, schedule listen again. */ + event_add_read(router->master, pim_msdp_sock_auth_accept, mp, + mp->auth_listen_sock, &mp->auth_listen_ev); + return; + } + + /* + * Previous connection still going. + * + * We must wait for the user to close the previous connection in order + * to establish the new one. User can manually force that by calling + * `clear ip msdp peer A.B.C.D`. + */ + if (mp->fd != -1) { + ++mp->pim->msdp.rejected_accepts; + if (PIM_DEBUG_MSDP_EVENTS) { + flog_err(EC_PIM_MSDP_PACKET, + "msdp peer connection refused from %pI4: old connection still running", + &sin.sin_addr); + } + close(sock); + + /* Unexpected connection, schedule listen again. */ + event_add_read(router->master, pim_msdp_sock_auth_accept, mp, + mp->auth_listen_sock, &mp->auth_listen_ev); + return; + } + + /* Unexpected client connected. */ + if (mp->peer.s_addr != sin.sin_addr.s_addr) { + ++mp->pim->msdp.rejected_accepts; + if (PIM_DEBUG_MSDP_EVENTS) { + flog_err(EC_PIM_MSDP_PACKET, + "msdp peer connection refused from %pI4", + &sin.sin_addr); + } + close(sock); + + /* Unexpected peer, schedule listen again. */ + event_add_read(router->master, pim_msdp_sock_auth_accept, mp, + mp->auth_listen_sock, &mp->auth_listen_ev); + return; + } + + if (PIM_DEBUG_MSDP_INTERNAL) + zlog_debug("MSDP peer %s accept success", mp->key_str); + + /* Configure socket. */ + mp->fd = sock; + set_nonblocking(mp->fd); + pim_msdp_update_sock_send_buffer_size(mp->fd); + pim_msdp_peer_established(mp); + + /* Stop listening. */ + close(mp->auth_listen_sock); + mp->auth_listen_sock = -1; +} + +int pim_msdp_sock_auth_listen(struct pim_msdp_peer *mp) +{ + /* Clear any listening connection if it exists. */ + event_cancel(&mp->auth_listen_ev); + if (mp->auth_listen_sock != -1) { + close(mp->auth_listen_sock); + mp->auth_listen_sock = -1; + } + + /* Start new listening socket. */ + mp->auth_listen_sock = _pim_msdp_sock_listen(mp->pim->vrf, mp); + if (mp->auth_listen_sock == -1) + return -1; + + /* Listen for connections and connected only with the expected end. */ + event_add_read(router->master, pim_msdp_sock_auth_accept, mp, + mp->auth_listen_sock, &mp->auth_listen_ev); + + return 0; +} + /* passive peer socket accept */ static void pim_msdp_sock_accept(struct event *thread) { @@ -91,6 +277,21 @@ static void pim_msdp_sock_accept(struct event *thread) return; } + /* + * If authentication is configured then we can not accept + * unauthenticated connections. + */ + if (mp->auth_type != MSDP_AUTH_NONE) { + ++pim->msdp.rejected_accepts; + if (PIM_DEBUG_MSDP_EVENTS) { + flog_err(EC_PIM_MSDP_PACKET, + "msdp peer unauthenticated connection refused from %pSU", + &su); + } + close(msdp_sock); + return; + } + if (PIM_DEBUG_MSDP_INTERNAL) { zlog_debug("MSDP peer %s accept success%s", mp->key_str, mp->fd >= 0 ? "(dup)" : ""); @@ -116,9 +317,6 @@ static void pim_msdp_sock_accept(struct event *thread) int pim_msdp_sock_listen(struct pim_instance *pim) { int sock; - int socklen; - struct sockaddr_in sin; - int rc; struct pim_msdp_listener *listener = &pim->msdp.listener; if (pim->msdp.flags & PIM_MSDPF_LISTENER) { @@ -126,72 +324,20 @@ int pim_msdp_sock_listen(struct pim_instance *pim) return 0; } - sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock < 0) { - flog_err_sys(EC_LIB_SOCKET, "socket: %s", safe_strerror(errno)); - return sock; - } + sock = _pim_msdp_sock_listen(pim->vrf, NULL); + if (sock == -1) + return -1; - memset(&sin, 0, sizeof(struct sockaddr_in)); - sin.sin_family = AF_INET; - sin.sin_port = htons(PIM_MSDP_TCP_PORT); - socklen = sizeof(struct sockaddr_in); + + memset(&listener->su.sin, 0, sizeof(listener->su.sin)); + listener->su.sin.sin_family = AF_INET; + listener->su.sin.sin_port = htons(PIM_MSDP_TCP_PORT); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin.sin_len = socklen; + listener->su.sin.sin_len = sizeof(listener->su.sin); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - sockopt_reuseaddr(sock); - sockopt_reuseport(sock); - - if (pim->vrf->vrf_id != VRF_DEFAULT) { - struct interface *ifp = - if_lookup_by_name(pim->vrf->name, pim->vrf->vrf_id); - if (!ifp) { - flog_err(EC_LIB_INTERFACE, - "%s: Unable to lookup vrf interface: %s", - __func__, pim->vrf->name); - close(sock); - return -1; - } - if (pim_socket_bind(sock, ifp)) { - flog_err_sys(EC_LIB_SOCKET, - "%s: Unable to bind to socket: %s", - __func__, safe_strerror(errno)); - close(sock); - return -1; - } - } - - frr_with_privs(&pimd_privs) { - /* bind to well known TCP port */ - rc = bind(sock, (struct sockaddr *)&sin, socklen); - } - - if (rc < 0) { - flog_err_sys(EC_LIB_SOCKET, - "pim_msdp_socket bind to port %d: %s", - ntohs(sin.sin_port), safe_strerror(errno)); - close(sock); - return rc; - } - - rc = listen(sock, 3 /* backlog */); - if (rc < 0) { - flog_err_sys(EC_LIB_SOCKET, "pim_msdp_socket listen: %s", - safe_strerror(errno)); - close(sock); - return rc; - } - - /* Set socket DSCP byte */ - if (setsockopt_ipv4_tos(sock, IPTOS_PREC_INTERNETCONTROL)) { - zlog_warn("can't set sockopt IP_TOS to MSDP socket %d: %s", - sock, safe_strerror(errno)); - } - /* add accept thread */ listener->fd = sock; - memcpy(&listener->su, &sin, socklen); event_add_read(pim->msdp.master, pim_msdp_sock_accept, pim, sock, &listener->thread); @@ -272,6 +418,14 @@ int pim_msdp_sock_connect(struct pim_msdp_peer *mp) mp->fd, safe_strerror(errno)); } + /* Set authentication (if configured). */ + if (mp->auth_key) { + frr_with_privs (&pimd_privs) { + sockopt_tcp_signature(mp->fd, &mp->su_peer, + mp->auth_key); + } + } + /* Connect to the remote mp. */ return (sockunion_connect(mp->fd, &mp->su_peer, htons(PIM_MSDP_TCP_PORT), 0)); diff --git a/pimd/pim_msdp_socket.h b/pimd/pim_msdp_socket.h index ae31664f9c..d2c601409a 100644 --- a/pimd/pim_msdp_socket.h +++ b/pimd/pim_msdp_socket.h @@ -6,6 +6,9 @@ #ifndef PIM_MSDP_SOCKET_H #define PIM_MSDP_SOCKET_H +struct pim_msdp_peer; + +int pim_msdp_sock_auth_listen(struct pim_msdp_peer *mp); int pim_msdp_sock_listen(struct pim_instance *pim); int pim_msdp_sock_connect(struct pim_msdp_peer *mp); #endif diff --git a/pimd/pim_nb.c b/pimd/pim_nb.c index 6f4e325220..72b5bdefc9 100644 --- a/pimd/pim_nb.c +++ b/pimd/pim_nb.c @@ -177,6 +177,19 @@ const struct frr_yang_module_info frr_pim_info = { .destroy = pim_msdp_peer_sa_filter_out_destroy, } }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer/authentication-type", + .cbs = { + .modify = pim_msdp_peer_authentication_type_modify, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer/authentication-key", + .cbs = { + .modify = pim_msdp_peer_authentication_key_modify, + .destroy = pim_msdp_peer_authentication_key_destroy, + } + }, { .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag", .cbs = { diff --git a/pimd/pim_nb.h b/pimd/pim_nb.h index 56153bafba..3c7ab49ab3 100644 --- a/pimd/pim_nb.h +++ b/pimd/pim_nb.h @@ -69,6 +69,9 @@ int pim_msdp_peer_sa_filter_in_modify(struct nb_cb_modify_args *args); int pim_msdp_peer_sa_filter_in_destroy(struct nb_cb_destroy_args *args); int pim_msdp_peer_sa_filter_out_modify(struct nb_cb_modify_args *args); int pim_msdp_peer_sa_filter_out_destroy(struct nb_cb_destroy_args *args); +int pim_msdp_peer_authentication_type_modify(struct nb_cb_modify_args *args); +int pim_msdp_peer_authentication_key_modify(struct nb_cb_modify_args *args); +int pim_msdp_peer_authentication_key_destroy(struct nb_cb_destroy_args *args); int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_create( struct nb_cb_create_args *args); int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_destroy( diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c index 49bd9a5ce7..328463c40e 100644 --- a/pimd/pim_nb_config.c +++ b/pimd/pim_nb_config.c @@ -15,6 +15,7 @@ #include "pim_pim.h" #include "pim_mlag.h" #include "pim_bfd.h" +#include "pim_msdp_socket.h" #include "pim_static.h" #include "pim_ssm.h" #include "pim_ssmpingd.h" @@ -1053,6 +1054,9 @@ pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address nb_cb_destroy_args); pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_create, nb_cb_create_args); +pim6_msdp_err(pim_msdp_peer_authentication_type_modify, nb_cb_modify_args); +pim6_msdp_err(pim_msdp_peer_authentication_key_modify, nb_cb_modify_args); +pim6_msdp_err(pim_msdp_peer_authentication_key_destroy, nb_cb_destroy_args); #if PIM_IPV != 6 /* @@ -1154,6 +1158,81 @@ int pim_msdp_mesh_group_source_destroy(struct nb_cb_destroy_args *args) return NB_OK; } +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer/authentication-type + */ +int pim_msdp_peer_authentication_type_modify(struct nb_cb_modify_args *args) +{ + struct pim_msdp_peer *mp; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + /* NOTHING */ + break; + case NB_EV_APPLY: + mp = nb_running_get_entry(args->dnode, NULL, true); + mp->auth_type = yang_dnode_get_enum(args->dnode, NULL); + break; + } + + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer/authentication-key + */ +int pim_msdp_peer_authentication_key_modify(struct nb_cb_modify_args *args) +{ + struct pim_msdp_peer *mp; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + if (strlen(yang_dnode_get_string(args->dnode, NULL)) > + TCP_MD5SIG_MAXKEYLEN) { + snprintf(args->errmsg, args->errmsg_len, + "MD5 authentication key too long"); + return NB_ERR_VALIDATION; + } + break; + case NB_EV_APPLY: + mp = nb_running_get_entry(args->dnode, NULL, true); + XFREE(MTYPE_PIM_MSDP_AUTH_KEY, mp->auth_key); + mp->auth_key = XSTRDUP(MTYPE_PIM_MSDP_AUTH_KEY, + yang_dnode_get_string(args->dnode, NULL)); + + /* We must start listening the new authentication key now. */ + if (PIM_MSDP_PEER_IS_LISTENER(mp)) + pim_msdp_sock_auth_listen(mp); + break; + } + + return NB_OK; +} + +int pim_msdp_peer_authentication_key_destroy(struct nb_cb_destroy_args *args) +{ + struct pim_msdp_peer *mp; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + /* NOTHING */ + break; + case NB_EV_APPLY: + mp = nb_running_get_entry(args->dnode, NULL, true); + XFREE(MTYPE_PIM_MSDP_AUTH_KEY, mp->auth_key); + break; + } + + return NB_OK; +} /* * XPath: