diff options
author | Abhishek N R <abnr@vmware.com> | 2022-12-14 07:34:25 +0100 |
---|---|---|
committer | Abhishek N R <abnr@vmware.com> | 2023-04-03 13:05:17 +0200 |
commit | bd2c824a21db78353125b4d2a4026b7a63071883 (patch) | |
tree | 98feb0e2c5485d12866c19f0ecd896e7597e64f8 /pimd | |
parent | Merge pull request #13182 from taspelund/add_bgp_json_comments (diff) | |
download | frr-bd2c824a21db78353125b4d2a4026b7a63071883.tar.xz frr-bd2c824a21db78353125b4d2a4026b7a63071883.zip |
pim6d: Impelmenting "ipv6 mld join"
Fixes: #12014
Signed-off-by: Abhishek N R <abnr@vmware.com>
Diffstat (limited to 'pimd')
-rw-r--r-- | pimd/pim_addr.h | 2 | ||||
-rw-r--r-- | pimd/pim_iface.c | 145 | ||||
-rw-r--r-- | pimd/pim_iface.h | 8 | ||||
-rw-r--r-- | pimd/pim_igmp_join.h | 55 | ||||
-rw-r--r-- | pimd/pim_nb_config.c | 59 | ||||
-rw-r--r-- | pimd/pim_vty.c | 33 | ||||
-rw-r--r-- | pimd/subdir.am | 1 | ||||
-rw-r--r-- | pimd/test_igmpv3_join.c | 6 |
8 files changed, 154 insertions, 155 deletions
diff --git a/pimd/pim_addr.h b/pimd/pim_addr.h index cc473d1f8..94c63bbcc 100644 --- a/pimd/pim_addr.h +++ b/pimd/pim_addr.h @@ -28,6 +28,7 @@ typedef struct in_addr pim_addr; #define PIM_MROUTE_DBG "mroute" #define PIMREG "pimreg" #define GM "IGMP" +#define IPPROTO_GM IPPROTO_IGMP #define PIM_ADDR_FUNCNAME(name) ipv4_##name @@ -57,6 +58,7 @@ typedef struct in6_addr pim_addr; #define PIM_MROUTE_DBG "mroute6" #define PIMREG "pim6reg" #define GM "MLD" +#define IPPROTO_GM IPPROTO_ICMPV6 #define PIM_ADDR_FUNCNAME(name) ipv6_##name diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index ead02d8bd..b053e422e 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -42,10 +42,10 @@ #if PIM_IPV == 4 static void pim_if_igmp_join_del_all(struct interface *ifp); -static int igmp_join_sock(const char *ifname, ifindex_t ifindex, - struct in_addr group_addr, struct in_addr source_addr, - struct pim_interface *pim_ifp); #endif +static int gm_join_sock(const char *ifname, ifindex_t ifindex, + pim_addr group_addr, pim_addr source_addr, + struct pim_interface *pim_ifp); void pim_if_init(struct pim_instance *pim) { @@ -560,7 +560,7 @@ void pim_if_addr_add(struct connected *ifc) /* Close socket and reopen with Source and Group */ close(ij->sock_fd); - join_fd = igmp_join_sock( + join_fd = gm_join_sock( ifp->name, ifp->ifindex, ij->group_addr, ij->source_addr, pim_ifp); if (join_fd < 0) { @@ -573,7 +573,7 @@ void pim_if_addr_add(struct connected *ifc) "<src?>", ij->source_addr, source_str, sizeof(source_str)); zlog_warn( - "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", + "%s: gm_join_sock() failure for IGMP group %s source %s on interface %s", __func__, group_str, source_str, ifp->name); /* warning only */ @@ -1214,15 +1214,13 @@ long pim_if_t_suppressed_msec(struct interface *ifp) return t_suppressed_msec; } -#if PIM_IPV == 4 -static void igmp_join_free(struct gm_join *ij) +static void gm_join_free(struct gm_join *ij) { XFREE(MTYPE_PIM_IGMP_JOIN, ij); } -static struct gm_join *igmp_join_find(struct list *join_list, - struct in_addr group_addr, - struct in_addr source_addr) +static struct gm_join *gm_join_find(struct list *join_list, pim_addr group_addr, + pim_addr source_addr) { struct listnode *node; struct gm_join *ij; @@ -1230,38 +1228,33 @@ static struct gm_join *igmp_join_find(struct list *join_list, assert(join_list); for (ALL_LIST_ELEMENTS_RO(join_list, node, ij)) { - if ((group_addr.s_addr == ij->group_addr.s_addr) - && (source_addr.s_addr == ij->source_addr.s_addr)) + if ((!pim_addr_cmp(group_addr, ij->group_addr)) && + (!pim_addr_cmp(source_addr, ij->source_addr))) return ij; } return 0; } -static int igmp_join_sock(const char *ifname, ifindex_t ifindex, - struct in_addr group_addr, struct in_addr source_addr, - struct pim_interface *pim_ifp) +static int gm_join_sock(const char *ifname, ifindex_t ifindex, + pim_addr group_addr, pim_addr source_addr, + struct pim_interface *pim_ifp) { int join_fd; pim_ifp->igmp_ifstat_joins_sent++; - join_fd = pim_socket_raw(IPPROTO_IGMP); + join_fd = pim_socket_raw(IPPROTO_GM); if (join_fd < 0) { pim_ifp->igmp_ifstat_joins_failed++; return -1; } - if (pim_igmp_join_source(join_fd, ifindex, group_addr, source_addr)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, - sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, - sizeof(source_str)); + if (pim_gm_join_source(join_fd, ifindex, group_addr, source_addr)) { zlog_warn( - "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s", - __func__, join_fd, group_str, source_str, ifindex, + "%s: setsockopt(fd=%d) failure for " GM + " group %pPAs source %pPAs ifindex %d on interface %s: errno=%d: %s", + __func__, join_fd, &group_addr, &source_addr, ifindex, ifname, errno, safe_strerror(errno)); pim_ifp->igmp_ifstat_joins_failed++; @@ -1273,10 +1266,8 @@ static int igmp_join_sock(const char *ifname, ifindex_t ifindex, return join_fd; } -#if PIM_IPV == 4 -static struct gm_join *igmp_join_new(struct interface *ifp, - struct in_addr group_addr, - struct in_addr source_addr) +static struct gm_join *gm_join_new(struct interface *ifp, pim_addr group_addr, + pim_addr source_addr) { struct pim_interface *pim_ifp; struct gm_join *ij; @@ -1285,19 +1276,12 @@ static struct gm_join *igmp_join_new(struct interface *ifp, pim_ifp = ifp->info; assert(pim_ifp); - join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr, - source_addr, pim_ifp); + join_fd = gm_join_sock(ifp->name, ifp->ifindex, group_addr, source_addr, + pim_ifp); if (join_fd < 0) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - - pim_inet4_dump("<grp?>", group_addr, group_str, - sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, - sizeof(source_str)); - zlog_warn( - "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", - __func__, group_str, source_str, ifp->name); + zlog_warn("%s: gm_join_sock() failure for " GM + " group %pPAs source %pPAs on interface %s", + __func__, &group_addr, &source_addr, ifp->name); return 0; } @@ -1312,11 +1296,9 @@ static struct gm_join *igmp_join_new(struct interface *ifp, return ij; } -#endif /* PIM_IPV == 4 */ -#if PIM_IPV == 4 -ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr, - struct in_addr source_addr) +ferr_r pim_if_gm_join_add(struct interface *ifp, pim_addr group_addr, + pim_addr source_addr) { struct pim_interface *pim_ifp; struct gm_join *ij; @@ -1329,37 +1311,32 @@ ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr, if (!pim_ifp->gm_join_list) { pim_ifp->gm_join_list = list_new(); - pim_ifp->gm_join_list->del = (void (*)(void *))igmp_join_free; + pim_ifp->gm_join_list->del = (void (*)(void *))gm_join_free; } - ij = igmp_join_find(pim_ifp->gm_join_list, group_addr, source_addr); + ij = gm_join_find(pim_ifp->gm_join_list, group_addr, source_addr); - /* This interface has already been configured to join this IGMP group + /* This interface has already been configured to join this IGMP/MLD + * group */ if (ij) { return ferr_ok(); } - (void)igmp_join_new(ifp, group_addr, source_addr); + (void)gm_join_new(ifp, group_addr, source_addr); if (PIM_DEBUG_GM_EVENTS) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, - sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, - sizeof(source_str)); zlog_debug( - "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s", - __func__, source_str, group_str, ifp->name); + "%s: issued static " GM + " join for channel (S,G)=(%pPA,%pPA) on interface %s", + __func__, &source_addr, &group_addr, ifp->name); } return ferr_ok(); } -#endif /* PIM_IPV == 4 */ -int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr, - struct in_addr source_addr) +int pim_if_gm_join_del(struct interface *ifp, pim_addr group_addr, + pim_addr source_addr) { struct pim_interface *pim_ifp; struct gm_join *ij; @@ -1372,40 +1349,29 @@ int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr, } if (!pim_ifp->gm_join_list) { - zlog_warn("%s: no IGMP join on interface %s", __func__, + zlog_warn("%s: no " GM " join on interface %s", __func__, ifp->name); return -2; } - ij = igmp_join_find(pim_ifp->gm_join_list, group_addr, source_addr); + ij = gm_join_find(pim_ifp->gm_join_list, group_addr, source_addr); if (!ij) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, - sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, - sizeof(source_str)); - zlog_warn( - "%s: could not find IGMP group %s source %s on interface %s", - __func__, group_str, source_str, ifp->name); + zlog_warn("%s: could not find " GM + " group %pPAs source %pPAs on interface %s", + __func__, &group_addr, &source_addr, ifp->name); return -3; } if (close(ij->sock_fd)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, - sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, - sizeof(source_str)); zlog_warn( - "%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s", - __func__, ij->sock_fd, group_str, source_str, ifp->name, - errno, safe_strerror(errno)); + "%s: failure closing sock_fd=%d for " GM + " group %pPAs source %pPAs on interface %s: errno=%d: %s", + __func__, ij->sock_fd, &group_addr, &source_addr, + ifp->name, errno, safe_strerror(errno)); /* warning only */ } listnode_delete(pim_ifp->gm_join_list, ij); - igmp_join_free(ij); + gm_join_free(ij); if (listcount(pim_ifp->gm_join_list) < 1) { list_delete(&pim_ifp->gm_join_list); pim_ifp->gm_join_list = 0; @@ -1414,6 +1380,7 @@ int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr, return 0; } +#if PIM_IPV == 4 __attribute__((unused)) static void pim_if_igmp_join_del_all(struct interface *ifp) { @@ -1433,21 +1400,9 @@ static void pim_if_igmp_join_del_all(struct interface *ifp) return; for (ALL_LIST_ELEMENTS(pim_ifp->gm_join_list, node, nextnode, ij)) - pim_if_igmp_join_del(ifp, ij->group_addr, ij->source_addr); + pim_if_gm_join_del(ifp, ij->group_addr, ij->source_addr); } -#else /* PIM_IPV != 4 */ -ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr, - struct in_addr source_addr) -{ - return ferr_ok(); -} - -int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr, - struct in_addr source_addr) -{ - return 0; -} -#endif /* PIM_IPV != 4 */ +#endif /* PIM_IPV == 4 */ /* RFC 4601 diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 0aff56d55..973840a75 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -217,10 +217,10 @@ int pim_if_t_override_msec(struct interface *ifp); pim_addr pim_find_primary_addr(struct interface *ifp); -ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr, - struct in_addr source_addr); -int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr, - struct in_addr source_addr); +ferr_r pim_if_gm_join_add(struct interface *ifp, pim_addr group_addr, + pim_addr source_addr); +int pim_if_gm_join_del(struct interface *ifp, pim_addr group_addr, + pim_addr source_addr); void pim_if_update_could_assert(struct interface *ifp); diff --git a/pimd/pim_igmp_join.h b/pimd/pim_igmp_join.h index d6d22be3e..0e9498c50 100644 --- a/pimd/pim_igmp_join.h +++ b/pimd/pim_igmp_join.h @@ -7,6 +7,8 @@ #ifndef PIM_IGMP_JOIN_H #define PIM_IGMP_JOIN_H +#include "pim_addr.h" + /* required headers #include'd by caller */ #ifndef SOL_IP @@ -26,35 +28,64 @@ struct group_source_req { }; #endif -static inline int pim_igmp_join_source(int fd, ifindex_t ifindex, - struct in_addr group_addr, - struct in_addr source_addr) +#if PIM_IPV == 4 +static inline int pim_gm_join_source(int fd, ifindex_t ifindex, + pim_addr group_addr, pim_addr source_addr) { struct group_source_req req; - struct sockaddr_in group; - struct sockaddr_in source; + struct sockaddr_in group = {}; + struct sockaddr_in source = {}; memset(&req, 0, sizeof(req)); - memset(&group, 0, sizeof(group)); - group.sin_family = AF_INET; + + group.sin_family = PIM_AF; group.sin_addr = group_addr; group.sin_port = htons(0); - memcpy(&req.gsr_group, &group, sizeof(struct sockaddr_in)); + memcpy(&req.gsr_group, &group, sizeof(group)); - memset(&source, 0, sizeof(source)); - source.sin_family = AF_INET; + source.sin_family = PIM_AF; source.sin_addr = source_addr; source.sin_port = htons(0); - memcpy(&req.gsr_source, &source, sizeof(struct sockaddr_in)); + memcpy(&req.gsr_source, &source, sizeof(source)); req.gsr_interface = ifindex; - if (source_addr.s_addr == INADDR_ANY) + if (pim_addr_is_any(source_addr)) return setsockopt(fd, SOL_IP, MCAST_JOIN_GROUP, &req, sizeof(req)); else return setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, &req, sizeof(req)); } +#else /* PIM_IPV != 4*/ +static inline int pim_gm_join_source(int fd, ifindex_t ifindex, + pim_addr group_addr, pim_addr source_addr) +{ + struct group_source_req req; + struct sockaddr_in6 group = {}; + struct sockaddr_in6 source = {}; + + memset(&req, 0, sizeof(req)); + + group.sin6_family = PIM_AF; + group.sin6_addr = group_addr; + group.sin6_port = htons(0); + memcpy(&req.gsr_group, &group, sizeof(group)); + + source.sin6_family = PIM_AF; + source.sin6_addr = source_addr; + source.sin6_port = htons(0); + memcpy(&req.gsr_source, &source, sizeof(source)); + + req.gsr_interface = ifindex; + + if (pim_addr_is_any(source_addr)) + return setsockopt(fd, SOL_IPV6, MCAST_JOIN_GROUP, &req, + sizeof(req)); + else + return setsockopt(fd, SOL_IPV6, MCAST_JOIN_SOURCE_GROUP, &req, + sizeof(req)); +} +#endif /* PIM_IPV != 4*/ #endif /* PIM_IGMP_JOIN_H */ diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c index fa6f66414..ff68a28a7 100644 --- a/pimd/pim_nb_config.c +++ b/pimd/pim_nb_config.c @@ -2880,10 +2880,9 @@ int lib_interface_gmp_address_family_robustness_variable_modify( int lib_interface_gmp_address_family_static_group_create( struct nb_cb_create_args *args) { -#if PIM_IPV == 4 struct interface *ifp; - struct ipaddr source_addr; - struct ipaddr group_addr; + pim_addr source_addr; + pim_addr group_addr; int result; const char *ifp_name; const struct lyd_node *if_dnode; @@ -2899,33 +2898,40 @@ int lib_interface_gmp_address_family_static_group_create( return NB_ERR_VALIDATION; } - yang_dnode_get_ip(&group_addr, args->dnode, "./group-addr"); - if (pim_is_group_224_0_0_0_24(group_addr.ip._v4_addr)) { + yang_dnode_get_pimaddr(&group_addr, args->dnode, + "./group-addr"); +#if PIM_IPV == 4 + if (pim_is_group_224_0_0_0_24(group_addr)) { snprintf( args->errmsg, args->errmsg_len, "Groups within 224.0.0.0/24 are reserved and cannot be joined"); return NB_ERR_VALIDATION; } +#else + if (ipv6_mcast_reserved(&group_addr)) { + snprintf( + args->errmsg, args->errmsg_len, + "Groups within ffx2::/16 are reserved and cannot be joined"); + return NB_ERR_VALIDATION; + } +#endif break; case NB_EV_PREPARE: case NB_EV_ABORT: break; case NB_EV_APPLY: ifp = nb_running_get_entry(args->dnode, NULL, true); - yang_dnode_get_ip(&source_addr, args->dnode, "./source-addr"); - yang_dnode_get_ip(&group_addr, args->dnode, "./group-addr"); - - result = pim_if_igmp_join_add(ifp, group_addr.ip._v4_addr, - source_addr.ip._v4_addr); + yang_dnode_get_pimaddr(&source_addr, args->dnode, + "./source-addr"); + yang_dnode_get_pimaddr(&group_addr, args->dnode, + "./group-addr"); + result = pim_if_gm_join_add(ifp, group_addr, source_addr); if (result) { snprintf(args->errmsg, args->errmsg_len, - "Failure joining IGMP group"); + "Failure joining " GM " group"); return NB_ERR_INCONSISTENCY; } } -#else - /* TBD Depends on MLD data structure changes */ -#endif /* PIM_IPV == 4 */ return NB_OK; } @@ -2933,8 +2939,8 @@ int lib_interface_gmp_address_family_static_group_destroy( struct nb_cb_destroy_args *args) { struct interface *ifp; - struct ipaddr source_addr; - struct ipaddr group_addr; + pim_addr source_addr; + pim_addr group_addr; int result; switch (args->event) { @@ -2944,22 +2950,17 @@ int lib_interface_gmp_address_family_static_group_destroy( break; case NB_EV_APPLY: ifp = nb_running_get_entry(args->dnode, NULL, true); - yang_dnode_get_ip(&source_addr, args->dnode, "./source-addr"); - yang_dnode_get_ip(&group_addr, args->dnode, "./group-addr"); - - result = pim_if_igmp_join_del(ifp, group_addr.ip._v4_addr, - source_addr.ip._v4_addr); + yang_dnode_get_pimaddr(&source_addr, args->dnode, + "./source-addr"); + yang_dnode_get_pimaddr(&group_addr, args->dnode, + "./group-addr"); + result = pim_if_gm_join_del(ifp, group_addr, source_addr); if (result) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - - ipaddr2str(&source_addr, src_str, sizeof(src_str)); - ipaddr2str(&group_addr, grp_str, sizeof(grp_str)); - snprintf(args->errmsg, args->errmsg_len, - "%% Failure leaving IGMP group %s %s on interface %s: %d", - src_str, grp_str, ifp->name, result); + "%% Failure leaving " GM + " group %pPAs %pPAs on interface %s: %d", + &source_addr, &group_addr, ifp->name, result); return NB_ERR_INCONSISTENCY; } diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 91628930f..0f6547ee2 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -335,18 +335,12 @@ static int gm_config_write(struct vty *vty, int writes, struct listnode *node; struct gm_join *ij; for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_join_list, node, ij)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", ij->group_addr, group_str, - sizeof(group_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); - } + if (pim_addr_is_any(ij->source_addr)) + vty_out(vty, " ip igmp join %pPAs\n", + &ij->group_addr); + else + vty_out(vty, " ip igmp join %pPAs %pPAs\n", + &ij->group_addr, &ij->source_addr); ++writes; } } @@ -388,6 +382,21 @@ static int gm_config_write(struct vty *vty, int writes, vty_out(vty, " ipv6 mld last-member-query-interval %d\n", pim_ifp->gm_specific_query_max_response_time_dsec); + /* IF ipv6 mld join */ + if (pim_ifp->gm_join_list) { + struct listnode *node; + struct gm_join *ij; + for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_join_list, node, ij)) { + if (pim_addr_is_any(ij->source_addr)) + vty_out(vty, " ipv6 mld join %pPAs\n", + &ij->group_addr); + else + vty_out(vty, " ipv6 mld join %pPAs %pPAs\n", + &ij->group_addr, &ij->source_addr); + ++writes; + } + } + return writes; } #endif diff --git a/pimd/subdir.am b/pimd/subdir.am index fd7255cb8..9a7901ec3 100644 --- a/pimd/subdir.am +++ b/pimd/subdir.am @@ -169,6 +169,7 @@ pimd_pim6d_CFLAGS = $(AM_CFLAGS) -DPIM_IPV=6 pimd_pim6d_LDADD = lib/libfrr.la $(LIBCAP) endif +pimd_test_igmpv3_join_CFLAGS = $(AM_CFLAGS) -DPIM_IPV=4 pimd_test_igmpv3_join_LDADD = lib/libfrr.la pimd_test_igmpv3_join_SOURCES = pimd/test_igmpv3_join.c diff --git a/pimd/test_igmpv3_join.c b/pimd/test_igmpv3_join.c index 07070900d..926e453c9 100644 --- a/pimd/test_igmpv3_join.c +++ b/pimd/test_igmpv3_join.c @@ -54,8 +54,8 @@ static int iface_solve_index(const char *ifname) int main(int argc, const char *argv[]) { - struct in_addr group_addr; - struct in_addr source_addr; + pim_addr group_addr; + pim_addr source_addr; const char *ifname; const char *group; const char *source; @@ -106,7 +106,7 @@ int main(int argc, const char *argv[]) exit(1); } - result = pim_igmp_join_source(fd, ifindex, group_addr, source_addr); + result = pim_gm_join_source(fd, ifindex, group_addr, source_addr); if (result) { fprintf(stderr, "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s\n", |