]> git.puffer.fish Git - matthieu/frr.git/commitdiff
pimd: add support for MSDP authentication
authorRafael Zalamena <rzalamena@opensourcerouting.org>
Wed, 7 Dec 2022 13:13:39 +0000 (10:13 -0300)
committerRafael Zalamena <rzalamena@opensourcerouting.org>
Mon, 29 Jul 2024 14:40:53 +0000 (11:40 -0300)
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 <rzalamena@opensourcerouting.org>
pimd/pim_cmd.c
pimd/pim_memory.c
pimd/pim_memory.h
pimd/pim_msdp.c
pimd/pim_msdp.h
pimd/pim_msdp_socket.c
pimd/pim_msdp_socket.h
pimd/pim_nb.c
pimd/pim_nb.h
pimd/pim_nb_config.c

index 1e3e090868b0e6a20a0cf0ed614789d28a137c0b..dcfad2a4f81ad5ae6f7b76fa046ed282815d52a3 100644 (file)
@@ -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);
index 85780f013b321f08d70c02c8e3f8c34ea36adaf5..604e24482d443d76a7e97f629a22b6783d2a57d3 100644 (file)
@@ -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");
index 41730e752284eb961f34416d024f25ed956eda84..353e09a71ccc8351e2b0e2073fdc2fd5fda9a985 100644 (file)
@@ -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);
index 0bb2d93a3a0b35dbaf8fba01eab1defe1087b2c5..215cc3c5029c83842f95555ceebffd68f35dd84c 100644 (file)
@@ -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)
 {
-       pim_msdp_peer_stop_tcp_conn(mp, true);
+       /* 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;
+       }
 
-       mp->local = *addr;
+       /* Stop previously running connection. */
+       pim_msdp_peer_stop_tcp_conn(mp, true);
 
+       /* 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);
index a45726cb85a68f29ede9e12e932b4f8ef7789fde..f77b0e1a3afd645b05b11bf9eb47eb8120155236 100644 (file)
@@ -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)
index fe8d5e934aca19b802fc8fa8672bdbf09b523231..2fb0bb87c7890798fc25ee5bd9af63f874cc7757 100644 (file)
@@ -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));
index ae31664f9ce6191c158b289f376403a6497015e2..d2c601409a5a08250e5bda9352afe5806fdaf514 100644 (file)
@@ -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
index 6f4e32522093f52efc1970569106d03c7d48777d..72b5bdefc92457c75331090b14665362fac6f978 100644 (file)
@@ -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 = {
index 56153bafbac0271ce2628d01edbe4bf564138317..3c7ab49ab31376f2a40127a2bdabf559fb880037 100644 (file)
@@ -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(
index 49bd9a5ce71a3b566c8d97ac5c4958c73a87953e..328463c40ebcc62b3c045ced495e679157281d42 100644 (file)
@@ -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: