From b84493132c2470fee3daf1be7262e88b86265e47 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 19 Aug 2021 16:46:30 +0200 Subject: [PATCH] pimd: allow restricting neighbors per interface Just filter incoming packets against a specified prefix-list. Signed-off-by: David Lamparter --- pimd/pim6_cmd.c | 30 +++++++++++++++++++++++++++ pimd/pim_cmd.c | 30 +++++++++++++++++++++++++++ pimd/pim_iface.c | 1 + pimd/pim_iface.h | 1 + pimd/pim_nb.c | 7 +++++++ pimd/pim_nb.h | 2 ++ pimd/pim_nb_config.c | 49 ++++++++++++++++++++++++++++++++++++++++++++ pimd/pim_pim.c | 38 ++++++++++++++++++++++++++++++++++ pimd/pim_vty.c | 6 ++++++ yang/frr-pim.yang | 6 ++++++ 10 files changed, 170 insertions(+) diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index 50357ca1d0..8297911828 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -1803,6 +1803,34 @@ DEFPY (interface_no_ipv6_mld_last_member_query_interval, return gm_process_no_last_member_query_interval_cmd(vty); } +DEFPY_YANG(interface_ipv6_pim_neighbor_prefix_list, + interface_ipv6_pim_neighbor_prefix_list_cmd, + "[no] ipv6 pim allowed-neighbors prefix-list PREFIXLIST6_NAME$prefix_list", + NO_STR + IP_STR + PIM_STR + "Restrict allowed PIM neighbors\n" + "Use prefix-list to filter neighbors\n" + "Name of a prefix-list\n") +{ + if (no) + nb_cli_enqueue_change(vty, "./neighbor-filter-prefix-list", NB_OP_DESTROY, NULL); + else + nb_cli_enqueue_change(vty, "./neighbor-filter-prefix-list", NB_OP_MODIFY, + prefix_list); + + return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH, FRR_PIM_AF_XPATH_VAL); +} + +ALIAS(interface_ipv6_pim_neighbor_prefix_list, + interface_no_ipv6_pim_neighbor_prefix_list_cmd, + "no ipv6 pim allowed-neighbors [prefix-list]", + NO_STR + IP_STR + PIM_STR + "Restrict allowed PIM neighbors\n" + "Use prefix-list to filter neighbors\n") + DEFPY (show_ipv6_pim_rp, show_ipv6_pim_rp_cmd, "show ipv6 pim [vrf NAME] rp-info [X:X::X:X/M$group] [json$json]", @@ -2973,6 +3001,8 @@ void pim_cmd_init(void) &interface_ipv6_mld_last_member_query_interval_cmd); install_element(INTERFACE_NODE, &interface_no_ipv6_mld_last_member_query_interval_cmd); + install_element(INTERFACE_NODE, &interface_ipv6_pim_neighbor_prefix_list_cmd); + install_element(INTERFACE_NODE, &interface_no_ipv6_pim_neighbor_prefix_list_cmd); install_element(VIEW_NODE, &show_ipv6_pim_rp_cmd); install_element(VIEW_NODE, &show_ipv6_pim_rp_vrf_all_cmd); diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 4ad75a21e7..f838c401e3 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -6035,6 +6035,34 @@ DEFPY (interface_ip_igmp_proxy, } +DEFPY_YANG(interface_ip_pim_neighbor_prefix_list, + interface_ip_pim_neighbor_prefix_list_cmd, + "[no] ip pim allowed-neighbors prefix-list WORD", + NO_STR + IP_STR + "pim multicast routing\n" + "Restrict allowed PIM neighbors\n" + "Use prefix-list to filter neighbors\n" + "Name of a prefix-list\n") +{ + if (no) + nb_cli_enqueue_change(vty, "./neighbor-filter-prefix-list", NB_OP_DESTROY, NULL); + else + nb_cli_enqueue_change(vty, "./neighbor-filter-prefix-list", NB_OP_MODIFY, + prefix_list); + + return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH, FRR_PIM_AF_XPATH_VAL); +} + +ALIAS (interface_ip_pim_neighbor_prefix_list, + interface_no_ip_pim_neighbor_prefix_list_cmd, + "no ip pim allowed-neighbors [prefix-list]", + NO_STR + IP_STR + "pim multicast routing\n" + "Restrict allowed PIM neighbors\n" + "Use prefix-list to filter neighbors\n") + DEFUN (debug_igmp, debug_igmp_cmd, "debug igmp", @@ -9169,6 +9197,8 @@ void pim_cmd_init(void) install_element(INTERFACE_NODE, &interface_no_ip_pim_boundary_oil_cmd); install_element(INTERFACE_NODE, &interface_ip_pim_boundary_acl_cmd); install_element(INTERFACE_NODE, &interface_ip_igmp_query_generate_cmd); + install_element(INTERFACE_NODE, &interface_ip_pim_neighbor_prefix_list_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_pim_neighbor_prefix_list_cmd); // Static mroutes NEB install_element(INTERFACE_NODE, &interface_ip_mroute_cmd); diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 8ec51ddc39..3408574cae 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -218,6 +218,7 @@ void pim_if_delete(struct interface *ifp) if (pim_ifp->bfd_config.profile) XFREE(MTYPE_TMP, pim_ifp->bfd_config.profile); + XFREE(MTYPE_PIM_PLIST_NAME, pim_ifp->nbr_plist); XFREE(MTYPE_PIM_INTERFACE, pim_ifp); ifp->info = NULL; diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 606fda6721..b0befcfcba 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -121,6 +121,7 @@ struct pim_interface { uint32_t pim_generation_id; uint16_t pim_propagation_delay_msec; /* config */ uint16_t pim_override_interval_msec; /* config */ + char *nbr_plist; struct list *pim_neighbor_list; /* list of struct pim_neighbor */ struct list *upstream_switch_list; struct pim_ifchannel_rb ifchannel_rb; diff --git a/pimd/pim_nb.c b/pimd/pim_nb.c index 3cd5c0f4e5..9a2fc5f3cd 100644 --- a/pimd/pim_nb.c +++ b/pimd/pim_nb.c @@ -314,6 +314,13 @@ const struct frr_yang_module_info frr_pim_info = { .destroy = lib_interface_pim_address_family_hello_holdtime_destroy, } }, + { + .xpath = "/frr-interface:lib/interface/frr-pim:pim/address-family/neighbor-filter-prefix-list", + .cbs = { + .modify = lib_interface_pim_address_family_nbr_plist_modify, + .destroy = lib_interface_pim_address_family_nbr_plist_destroy, + } + }, { .xpath = "/frr-interface:lib/interface/frr-pim:pim/address-family/bfd", .cbs = { diff --git a/pimd/pim_nb.h b/pimd/pim_nb.h index ce7b5e43af..e9faf875b0 100644 --- a/pimd/pim_nb.h +++ b/pimd/pim_nb.h @@ -110,6 +110,8 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mc struct nb_cb_modify_args *args); int lib_interface_pim_address_family_dr_priority_modify( struct nb_cb_modify_args *args); +int lib_interface_pim_address_family_nbr_plist_modify(struct nb_cb_modify_args *args); +int lib_interface_pim_address_family_nbr_plist_destroy(struct nb_cb_destroy_args *args); int lib_interface_pim_address_family_create(struct nb_cb_create_args *args); int lib_interface_pim_address_family_destroy(struct nb_cb_destroy_args *args); int lib_interface_pim_address_family_pim_enable_modify( diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c index d671ea3b65..1be5e9cb88 100644 --- a/pimd/pim_nb_config.c +++ b/pimd/pim_nb_config.c @@ -2163,6 +2163,55 @@ int lib_interface_pim_address_family_hello_holdtime_destroy( return NB_OK; } + +/* + * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/neighbor-filter-prefix-list + */ +int lib_interface_pim_address_family_nbr_plist_modify(struct nb_cb_modify_args *args) +{ + struct interface *ifp; + struct pim_interface *pim_ifp; + const char *plist; + + plist = yang_dnode_get_string(args->dnode, NULL); + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_ABORT: + case NB_EV_PREPARE: + break; + case NB_EV_APPLY: + ifp = nb_running_get_entry(args->dnode, NULL, true); + pim_ifp = ifp->info; + + XFREE(MTYPE_PIM_PLIST_NAME, pim_ifp->nbr_plist); + pim_ifp->nbr_plist = XSTRDUP(MTYPE_PIM_PLIST_NAME, plist); + break; + } + + return NB_OK; +} + +int lib_interface_pim_address_family_nbr_plist_destroy(struct nb_cb_destroy_args *args) +{ + struct interface *ifp; + struct pim_interface *pim_ifp; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_ABORT: + case NB_EV_PREPARE: + break; + case NB_EV_APPLY: + ifp = nb_running_get_entry(args->dnode, NULL, true); + pim_ifp = ifp->info; + XFREE(MTYPE_PIM_PLIST_NAME, pim_ifp->nbr_plist); + break; + } + + return NB_OK; +} + /* * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd */ diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index a41bbacea7..fb78e39022 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -149,6 +149,9 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len, uint32_t pim_msg_len = 0; uint16_t pim_checksum; /* received checksum */ uint16_t checksum; /* computed checksum */ + struct pim_interface *pim_ifp = ifp->info; + struct prefix src_prefix; + struct prefix_list *nbr_plist = NULL; struct pim_neighbor *neigh; struct pim_msg_header *header; bool no_fwd; @@ -205,6 +208,41 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len, return -1; } + switch (header->type) { + case PIM_MSG_TYPE_HELLO: + case PIM_MSG_TYPE_JOIN_PRUNE: + case PIM_MSG_TYPE_ASSERT: + if (pim_ifp == NULL || pim_ifp->nbr_plist == NULL) + break; + + nbr_plist = prefix_list_lookup(PIM_AFI, pim_ifp->nbr_plist); + +#if PIM_IPV == 4 + src_prefix.family = AF_INET; + src_prefix.prefixlen = IPV4_MAX_BITLEN; + src_prefix.u.prefix4 = sg.src; +#else + src_prefix.family = AF_INET6; + src_prefix.prefixlen = IPV6_MAX_BITLEN; + src_prefix.u.prefix6 = sg.src; +#endif + + if (nbr_plist && + prefix_list_apply_ext(nbr_plist, NULL, &src_prefix, true) == PREFIX_PERMIT) + break; + +#if PIM_IPV == 4 + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("neighbor filter rejects packet %pI4 -> %pI4 on %s", + &ip_hdr->ip_src, &ip_hdr->ip_dst, ifp->name); +#else + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("neighbor filter rejects packet %pI6 -> %pI6 on %s", &sg.src, + &sg.grp, ifp->name); +#endif + return -1; + } + /* save received checksum */ pim_checksum = header->checksum; diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index b2525998a6..e37703be2b 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -477,6 +477,12 @@ int pim_config_write(struct vty *vty, int writes, struct interface *ifp, ++writes; } + if (pim_ifp->nbr_plist) { + vty_out(vty, " " PIM_AF_NAME " pim allowed-neighbors prefix-list %s\n", + pim_ifp->nbr_plist); + ++writes; + } + /* IF ip pim drpriority */ if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) { vty_out(vty, " " PIM_AF_NAME " pim drpriority %u\n", diff --git a/yang/frr-pim.yang b/yang/frr-pim.yang index 6b6870f666..e0d8800f3e 100644 --- a/yang/frr-pim.yang +++ b/yang/frr-pim.yang @@ -516,6 +516,12 @@ module frr-pim { "Hello holdtime"; } + leaf neighbor-filter-prefix-list { + type plist-ref; + description + "Prefix-List to filter allowed PIM neighbors."; + } + container bfd { presence "Enable BFD support on the interface.";