From 771ce8ad240b0c620e6cf46a7841fe2b757f9b43 Mon Sep 17 00:00:00 2001 From: Liam McBirnie Date: Thu, 5 Dec 2019 21:57:50 +0100 Subject: [PATCH] pimd: Add command to join any-source multicast. Allow 'ip igmp join' to join group for any source if no source is specified. Disallow joining source "0.0.0.0" as it is used to define an any-source multicast group. Signed-off-by: Liam McBirnie --- doc/user/pim.rst | 6 +++--- pimd/pim_cmd.c | 47 +++++++++++++++++++++++++++++++------------- pimd/pim_igmp_join.h | 12 +++++++++-- pimd/pim_vty.c | 20 ++++++++++++------- 4 files changed, 59 insertions(+), 26 deletions(-) diff --git a/doc/user/pim.rst b/doc/user/pim.rst index 4f9c573a24..7b0090d34b 100644 --- a/doc/user/pim.rst +++ b/doc/user/pim.rst @@ -211,10 +211,10 @@ is in a vrf, enter the interface command with the vrf keyword at the end. Tell pim to receive IGMP reports and Query on this interface. The default version is v3. This command is useful on a LHR. -.. index:: ip igmp join A.B.C.D A.B.C.D -.. clicmd:: ip igmp join A.B.C.D A.B.C.D +.. index:: ip igmp join A.B.C.D [A.B.C.D] +.. clicmd:: ip igmp join A.B.C.D [A.B.C.D] - Join multicast source-group on an interface. + Join multicast group or source-group on an interface. .. index:: ip igmp query-interval (1-1800) .. clicmd:: ip igmp query-interval (1-1800) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index e5686a94f4..67204730df 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -6707,7 +6707,7 @@ DEFUN (interface_no_ip_igmp, DEFUN (interface_ip_igmp_join, interface_ip_igmp_join_cmd, - "ip igmp join A.B.C.D A.B.C.D", + "ip igmp join A.B.C.D [A.B.C.D]", IP_STR IFACE_IGMP_STR "IGMP join multicast group\n" @@ -6733,12 +6733,21 @@ DEFUN (interface_ip_igmp_join, } /* Source address */ - source_str = argv[idx_ipv4_2]->arg; - result = inet_pton(AF_INET, source_str, &source_addr); - if (result <= 0) { - vty_out(vty, "Bad source address %s: errno=%d: %s\n", - source_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; + if (argc == (idx_ipv4_2 + 1)) { + source_str = argv[idx_ipv4_2]->arg; + result = inet_pton(AF_INET, source_str, &source_addr); + if (result <= 0) { + vty_out(vty, "Bad source address %s: errno=%d: %s\n", + source_str, errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + /* Reject 0.0.0.0. Reserved for any source. */ + if (source_addr.s_addr == INADDR_ANY) { + vty_out(vty, "Bad source address %s\n", source_str); + return CMD_WARNING_CONFIG_FAILED; + } + } else { + source_addr.s_addr = INADDR_ANY; } CMD_FERR_RETURN(pim_if_igmp_join_add(ifp, group_addr, source_addr), @@ -6749,7 +6758,7 @@ DEFUN (interface_ip_igmp_join, DEFUN (interface_no_ip_igmp_join, interface_no_ip_igmp_join_cmd, - "no ip igmp join A.B.C.D A.B.C.D", + "no ip igmp join A.B.C.D [A.B.C.D]", NO_STR IP_STR IFACE_IGMP_STR @@ -6776,12 +6785,22 @@ DEFUN (interface_no_ip_igmp_join, } /* Source address */ - source_str = argv[idx_ipv4_2]->arg; - result = inet_pton(AF_INET, source_str, &source_addr); - if (result <= 0) { - vty_out(vty, "Bad source address %s: errno=%d: %s\n", - source_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; + if (argc == (idx_ipv4_2 + 1)) { + source_str = argv[idx_ipv4_2]->arg; + result = inet_pton(AF_INET, source_str, &source_addr); + if (result <= 0) { + vty_out(vty, "Bad source address %s: errno=%d: %s\n", + source_str, errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + /* Reject 0.0.0.0. Reserved for any source. */ + if (source_addr.s_addr == INADDR_ANY) { + vty_out(vty, "Bad source address %s\n", source_str); + return CMD_WARNING_CONFIG_FAILED; + } + } else { + source_str = "*"; + source_addr.s_addr = INADDR_ANY; } result = pim_if_igmp_join_del(ifp, group_addr, source_addr); diff --git a/pimd/pim_igmp_join.h b/pimd/pim_igmp_join.h index 88385bffba..c323902764 100644 --- a/pimd/pim_igmp_join.h +++ b/pimd/pim_igmp_join.h @@ -26,6 +26,10 @@ #define SOL_IP IPPROTO_IP #endif +#ifndef MCAST_JOIN_GROUP +#define MCAST_JOIN_GROUP 42 +#endif + #ifndef MCAST_JOIN_SOURCE_GROUP #define MCAST_JOIN_SOURCE_GROUP 46 struct group_source_req { @@ -58,8 +62,12 @@ static int pim_igmp_join_source(int fd, ifindex_t ifindex, req.gsr_interface = ifindex; - return setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, &req, - sizeof(req)); + if (source_addr.s_addr == INADDR_ANY) + return setsockopt(fd, SOL_IP, MCAST_JOIN_GROUP, &req, + sizeof(req)); + else + return setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, &req, + sizeof(req)); } #endif /* PIM_IGMP_JOIN_H */ diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 1c4ecf299f..c48ec373f8 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -379,13 +379,19 @@ int pim_interface_config_write(struct vty *vty) ij->group_addr, group_str, sizeof(group_str)); - inet_ntop(AF_INET, - &ij->source_addr, - source_str, - sizeof(source_str)); - vty_out(vty, - " ip igmp join %s %s\n", - group_str, source_str); + if (ij->source_addr.s_addr == INADDR_ANY) { + vty_out(vty, + " ip igmp join %s\n", + group_str); + } else { + inet_ntop(AF_INET, + &ij->source_addr, + source_str, + sizeof(source_str)); + vty_out(vty, + " ip igmp join %s %s\n", + group_str, source_str); + } ++writes; } }