Merge pull request #12459 from opensourcerouting/msdp-auth-v2

pimd: MSDP peer MD5 authentication
This commit is contained in:
Donald Sharp 2024-07-30 08:03:07 -04:00 committed by GitHub
commit b8747d81a5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 527 additions and 68 deletions

View File

@ -386,6 +386,17 @@ Commands available for MSDP:
The filtering will only take effect starting from the command The filtering will only take effect starting from the command
application. application.
.. clicmd:: msdp peer A.B.C.D password WORD
Use MD5 authentication to connect with the remote peer.
.. note::
The authentication will only take effect when starting a new
connection.
To apply it immediately call `clear ip msdp peer A.B.C.D`.
.. _show-pim-information: .. _show-pim-information:
@ -715,6 +726,13 @@ Clear commands reset various variables.
removes the next hop tracking for the bsr and resets the upstreams removes the next hop tracking for the bsr and resets the upstreams
for the dynamically learnt RPs. for the dynamically learnt RPs.
.. clicmd:: clear ip msdp peer A.B.C.D
Reset MSDP peer connection.
Use this command to set/unset MD5 authentication.
PIM EVPN configuration PIM EVPN configuration
====================== ======================
To use PIM in the underlay for overlay BUM forwarding associate a multicast To use PIM in the underlay for overlay BUM forwarding associate a multicast

View File

@ -60,6 +60,16 @@ extern int setsockopt_ipv6_tclass(int, int);
(((af) == AF_INET) : SOPT_SIZE_CMSG_IFINDEX_IPV4() \ (((af) == AF_INET) : SOPT_SIZE_CMSG_IFINDEX_IPV4() \
? SOPT_SIZE_CMSG_PKTINFO_IPV6()) ? SOPT_SIZE_CMSG_PKTINFO_IPV6())
/*
* If not defined then define the value for `TCP_MD5SIG_MAXKEYLEN`. This seems
* to be unavailable for NetBSD 8, FreeBSD 11 and FreeBSD 12.
*
* The value below was copied from `linux/tcp.h` from the Linux kernel headers.
*/
#ifndef TCP_MD5SIG_MAXKEYLEN
#define TCP_MD5SIG_MAXKEYLEN 80
#endif
extern int setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr, extern int setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr,
ifindex_t ifindex); ifindex_t ifindex);
extern int setsockopt_ipv4_multicast(int sock, int optname, extern int setsockopt_ipv4_multicast(int sock, int optname,

View File

@ -2823,6 +2823,39 @@ DEFPY (clear_ip_mroute_count,
return clear_ip_mroute_count_command(vty, name); 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, DEFPY (show_ip_mroute_count,
show_ip_mroute_count_cmd, show_ip_mroute_count_cmd,
"show ip mroute [vrf NAME] count [json$json]", "show ip mroute [vrf NAME] count [json$json]",
@ -6285,6 +6318,57 @@ DEFPY_ATTR(ip_pim_msdp_peer,
return ret; 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, DEFPY(pim_msdp_timers, pim_msdp_timers_cmd,
"msdp timers (1-65535)$keepalive (1-65535)$holdtime [(1-65535)$connretry]", "msdp timers (1-65535)$keepalive (1-65535)$holdtime [(1-65535)$connretry]",
CFG_MSDP_STR CFG_MSDP_STR
@ -8320,6 +8404,8 @@ void pim_cmd_init(void)
install_element(PIM_NODE, &pim_msdp_peer_cmd); install_element(PIM_NODE, &pim_msdp_peer_cmd);
install_element(PIM_NODE, &no_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, &pim_msdp_timers_cmd);
install_element(PIM_NODE, &no_pim_msdp_timers_cmd); install_element(PIM_NODE, &no_pim_msdp_timers_cmd);
install_element(PIM_NODE, &msdp_peer_sa_filter_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, &pim_test_sg_keepalive_cmd);
install_element(ENABLE_NODE, &clear_ip_mroute_count_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_interfaces_cmd);
install_element(ENABLE_NODE, &clear_ip_igmp_interfaces_cmd); install_element(ENABLE_NODE, &clear_ip_igmp_interfaces_cmd);
install_element(ENABLE_NODE, &clear_ip_mroute_cmd); install_element(ENABLE_NODE, &clear_ip_mroute_cmd);

View 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_FILTER_NAME, "PIM RP filter info");
DEFINE_MTYPE(PIMD, PIM_MSDP_PEER, "PIM MSDP peer"); 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_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_SA, "PIM MSDP source-active cache");
DEFINE_MTYPE(PIMD, PIM_MSDP_MG, "PIM MSDP mesh group"); DEFINE_MTYPE(PIMD, PIM_MSDP_MG, "PIM MSDP mesh group");
DEFINE_MTYPE(PIMD, PIM_MSDP_MG_MBR, "PIM MSDP mesh group mbr"); DEFINE_MTYPE(PIMD, PIM_MSDP_MG_MBR, "PIM MSDP mesh group mbr");

View File

@ -28,6 +28,7 @@ DECLARE_MTYPE(PIM_MSDP_MG_NAME);
DECLARE_MTYPE(PIM_MSDP_SA); DECLARE_MTYPE(PIM_MSDP_SA);
DECLARE_MTYPE(PIM_MSDP_MG); DECLARE_MTYPE(PIM_MSDP_MG);
DECLARE_MTYPE(PIM_MSDP_MG_MBR); DECLARE_MTYPE(PIM_MSDP_MG_MBR);
DECLARE_MTYPE(PIM_MSDP_AUTH_KEY);
DECLARE_MTYPE(PIM_SEC_ADDR); DECLARE_MTYPE(PIM_SEC_ADDR);
DECLARE_MTYPE(PIM_JP_AGG_GROUP); DECLARE_MTYPE(PIM_JP_AGG_GROUP);
DECLARE_MTYPE(PIM_JP_AGG_SOURCE); DECLARE_MTYPE(PIM_JP_AGG_SOURCE);

View 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 * first listening peer is configured; but don't bother tearing it down
* when * when
* all the peers go down */ * 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 /* 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->state = PIM_MSDP_INACTIVE;
mp->fd = -1; mp->fd = -1;
mp->auth_listen_sock = -1;
strlcpy(mp->last_reset, "-", sizeof(mp->last_reset)); strlcpy(mp->last_reset, "-", sizeof(mp->last_reset));
/* higher IP address is listener */ /* higher IP address is listener */
if (ntohl(mp->local.s_addr) > ntohl(mp->peer.s_addr)) { 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); 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); XFREE(MTYPE_PIM_MSDP_MG_NAME, mp->mesh_group_name);
mp->pim = NULL; mp->pim = NULL;
@ -1128,19 +1138,32 @@ void pim_msdp_peer_del(struct pim_msdp_peer **mp)
*mp = NULL; *mp = NULL;
} }
void pim_msdp_peer_change_source(struct pim_msdp_peer *mp, void pim_msdp_peer_restart(struct pim_msdp_peer *mp)
const struct in_addr *addr)
{ {
/* 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); pim_msdp_peer_stop_tcp_conn(mp, true);
mp->local = *addr; /* Start connection again. */
if (PIM_MSDP_PEER_IS_LISTENER(mp)) if (PIM_MSDP_PEER_IS_LISTENER(mp))
pim_msdp_peer_listen(mp); pim_msdp_peer_listen(mp);
else else
pim_msdp_peer_connect(mp); 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 */ /* peer hash and peer list helpers */
static unsigned int pim_msdp_peer_hash_key_make(const void *p) 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, vty_out(vty, " msdp peer %pI4 source %pI4\n", &mp->peer,
&mp->local); &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) if (mp->acl_in)
vty_out(vty, " msdp peer %pI4 sa-filter %s in\n", vty_out(vty, " msdp peer %pI4 sa-filter %s in\n",
&mp->peer, mp->acl_in); &mp->peer, mp->acl_in);

View File

@ -89,6 +89,11 @@ enum pim_msdp_peer_flags {
PIM_MSDP_PEERF_IN_GROUP = (1 << 2), 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_msdp_peer {
struct pim_instance *pim; struct pim_instance *pim;
@ -98,6 +103,13 @@ struct pim_msdp_peer {
char *mesh_group_name; char *mesh_group_name;
char key_str[INET_ADDRSTRLEN]; 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 */ /* state */
enum pim_msdp_peer_state state; enum pim_msdp_peer_state state;
enum pim_msdp_peer_flags flags; 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, void pim_msdp_peer_change_source(struct pim_msdp_peer *mp,
const struct in_addr *addr); 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 */ #else /* PIM_IPV == 6 */
static inline void pim_msdp_init(struct pim_instance *pim, static inline void pim_msdp_init(struct pim_instance *pim,
struct event_loop *master) struct event_loop *master)

View 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 */ /* passive peer socket accept */
static void pim_msdp_sock_accept(struct event *thread) static void pim_msdp_sock_accept(struct event *thread)
{ {
@ -91,6 +277,21 @@ static void pim_msdp_sock_accept(struct event *thread)
return; 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) { if (PIM_DEBUG_MSDP_INTERNAL) {
zlog_debug("MSDP peer %s accept success%s", mp->key_str, zlog_debug("MSDP peer %s accept success%s", mp->key_str,
mp->fd >= 0 ? "(dup)" : ""); 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 pim_msdp_sock_listen(struct pim_instance *pim)
{ {
int sock; int sock;
int socklen;
struct sockaddr_in sin;
int rc;
struct pim_msdp_listener *listener = &pim->msdp.listener; struct pim_msdp_listener *listener = &pim->msdp.listener;
if (pim->msdp.flags & PIM_MSDPF_LISTENER) { if (pim->msdp.flags & PIM_MSDPF_LISTENER) {
@ -126,72 +324,20 @@ int pim_msdp_sock_listen(struct pim_instance *pim)
return 0; return 0;
} }
sock = socket(AF_INET, SOCK_STREAM, 0); sock = _pim_msdp_sock_listen(pim->vrf, NULL);
if (sock < 0) { if (sock == -1)
flog_err_sys(EC_LIB_SOCKET, "socket: %s", safe_strerror(errno)); return -1;
return sock;
}
memset(&sin, 0, sizeof(struct sockaddr_in));
sin.sin_family = AF_INET; memset(&listener->su.sin, 0, sizeof(listener->su.sin));
sin.sin_port = htons(PIM_MSDP_TCP_PORT); listener->su.sin.sin_family = AF_INET;
socklen = sizeof(struct sockaddr_in); listener->su.sin.sin_port = htons(PIM_MSDP_TCP_PORT);
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN #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 */ #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 */ /* add accept thread */
listener->fd = sock; listener->fd = sock;
memcpy(&listener->su, &sin, socklen);
event_add_read(pim->msdp.master, pim_msdp_sock_accept, pim, sock, event_add_read(pim->msdp.master, pim_msdp_sock_accept, pim, sock,
&listener->thread); &listener->thread);
@ -272,6 +418,14 @@ int pim_msdp_sock_connect(struct pim_msdp_peer *mp)
mp->fd, safe_strerror(errno)); 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. */ /* Connect to the remote mp. */
return (sockunion_connect(mp->fd, &mp->su_peer, return (sockunion_connect(mp->fd, &mp->su_peer,
htons(PIM_MSDP_TCP_PORT), 0)); htons(PIM_MSDP_TCP_PORT), 0));

View File

@ -6,6 +6,9 @@
#ifndef PIM_MSDP_SOCKET_H #ifndef PIM_MSDP_SOCKET_H
#define 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_listen(struct pim_instance *pim);
int pim_msdp_sock_connect(struct pim_msdp_peer *mp); int pim_msdp_sock_connect(struct pim_msdp_peer *mp);
#endif #endif

View File

@ -177,6 +177,19 @@ const struct frr_yang_module_info frr_pim_info = {
.destroy = pim_msdp_peer_sa_filter_out_destroy, .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", .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag",
.cbs = { .cbs = {

View 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_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_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_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( int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_create(
struct nb_cb_create_args *args); struct nb_cb_create_args *args);
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_destroy( int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_destroy(

View File

@ -9,12 +9,14 @@
#include "pimd.h" #include "pimd.h"
#include "pim_nb.h" #include "pim_nb.h"
#include "lib/northbound_cli.h" #include "lib/northbound_cli.h"
#include "lib/sockopt.h"
#include "pim_igmpv3.h" #include "pim_igmpv3.h"
#include "pim_neighbor.h" #include "pim_neighbor.h"
#include "pim_nht.h" #include "pim_nht.h"
#include "pim_pim.h" #include "pim_pim.h"
#include "pim_mlag.h" #include "pim_mlag.h"
#include "pim_bfd.h" #include "pim_bfd.h"
#include "pim_msdp_socket.h"
#include "pim_static.h" #include "pim_static.h"
#include "pim_ssm.h" #include "pim_ssm.h"
#include "pim_ssmpingd.h" #include "pim_ssmpingd.h"
@ -1053,6 +1055,9 @@ pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address
nb_cb_destroy_args); nb_cb_destroy_args);
pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_create, pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_create,
nb_cb_create_args); 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 #if PIM_IPV != 6
/* /*
@ -1154,6 +1159,81 @@ int pim_msdp_mesh_group_source_destroy(struct nb_cb_destroy_args *args)
return NB_OK; 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: * XPath:

View File

@ -20,3 +20,7 @@ ip msdp peer 192.168.0.2 source 192.168.0.1
ip msdp peer 192.168.1.2 source 192.168.1.1 ip msdp peer 192.168.1.2 source 192.168.1.1
ip pim rp 10.254.254.1 ip pim rp 10.254.254.1
ip pim join-prune-interval 5 ip pim join-prune-interval 5
!
router pim
msdp peer 192.168.0.2 password 1234
!

View File

@ -16,3 +16,7 @@ ip msdp peer 192.168.0.1 source 192.168.0.2
ip msdp peer 192.168.2.2 source 192.168.2.1 ip msdp peer 192.168.2.2 source 192.168.2.1
ip pim rp 10.254.254.2 ip pim rp 10.254.254.2
ip pim join-prune-interval 5 ip pim join-prune-interval 5
!
router pim
msdp peer 192.168.0.1 password 1234
!

View File

@ -122,6 +122,37 @@ module frr-pim {
} }
} }
grouping msdp-authentication {
description
"MSDP authentication options.";
leaf authentication-type {
type enumeration {
enum None {
value 0;
description
"No authentication.";
}
enum MD5 {
value 1;
description
"Use MD5 digest.";
}
}
default None;
description
"Authentication method.";
}
leaf authentication-key {
when "../authentication-type = 'MD5'";
mandatory true;
type string;
description
"Authentication key.";
}
}
grouping global-pim-config-attributes { grouping global-pim-config-attributes {
description description
"A grouping defining per address family pim global attributes"; "A grouping defining per address family pim global attributes";
@ -283,6 +314,8 @@ module frr-pim {
description description
"Access list name used to filter the outgoing SAs exchanged."; "Access list name used to filter the outgoing SAs exchanged.";
} }
uses msdp-authentication;
} }
container mlag { container mlag {