From 1c56018f66723a5ea478f0d6607a8f81f4d6ada5 Mon Sep 17 00:00:00 2001 From: Balaji Gurudoss Date: Fri, 25 Feb 2022 15:59:03 +0530 Subject: [PATCH] pim6d: Changes done in pim_ssmpingd to support v6 Signed-off-by: Balaji Gurudoss --- pimd/pim_instance.h | 2 +- pimd/pim_nb_config.c | 36 +++--- pimd/pim_ssmpingd.c | 266 ++++++++++++++++++++----------------------- pimd/pim_ssmpingd.h | 6 +- pimd/pim_vty.c | 6 +- 5 files changed, 147 insertions(+), 169 deletions(-) diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h index 68c5b9167b..4ac9ef7f51 100644 --- a/pimd/pim_instance.h +++ b/pimd/pim_instance.h @@ -176,7 +176,7 @@ struct pim_instance { struct pim_vxlan_instance vxlan; struct list *ssmpingd_list; - struct in_addr ssmpingd_group_addr; + pim_addr ssmpingd_group_addr; unsigned int igmp_group_count; unsigned int igmp_watermark_limit; diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c index 21f57e2d11..2fabee5dfd 100644 --- a/pimd/pim_nb_config.c +++ b/pimd/pim_nb_config.c @@ -930,7 +930,7 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ss struct vrf *vrf; struct pim_instance *pim; int result; - struct ipaddr source_addr; + pim_addr source_addr; switch (args->event) { case NB_EV_VALIDATE: @@ -940,16 +940,14 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ss case NB_EV_APPLY: vrf = nb_running_get_entry(args->dnode, NULL, true); pim = vrf->info; - yang_dnode_get_ip(&source_addr, args->dnode, NULL); - result = pim_ssmpingd_start(pim, source_addr.ip._v4_addr); + yang_dnode_get_pimaddr(&source_addr, args->dnode, + "./source-addr"); + result = pim_ssmpingd_start(pim, source_addr); if (result) { - char source_str[INET_ADDRSTRLEN]; - - ipaddr2str(&source_addr, source_str, - sizeof(source_str)); - snprintf(args->errmsg, args->errmsg_len, - "%% Failure starting ssmpingd for source %s: %d", - source_str, result); + snprintf( + args->errmsg, args->errmsg_len, + "%% Failure starting ssmpingd for source %pPA: %d", + &source_addr, result); return NB_ERR_INCONSISTENCY; } } @@ -963,7 +961,7 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ss struct vrf *vrf; struct pim_instance *pim; int result; - struct ipaddr source_addr; + pim_addr source_addr; switch (args->event) { case NB_EV_VALIDATE: @@ -973,16 +971,14 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ss case NB_EV_APPLY: vrf = nb_running_get_entry(args->dnode, NULL, true); pim = vrf->info; - yang_dnode_get_ip(&source_addr, args->dnode, NULL); - result = pim_ssmpingd_stop(pim, source_addr.ip._v4_addr); + yang_dnode_get_pimaddr(&source_addr, args->dnode, + "./source-addr"); + result = pim_ssmpingd_stop(pim, source_addr); if (result) { - char source_str[INET_ADDRSTRLEN]; - - ipaddr2str(&source_addr, source_str, - sizeof(source_str)); - snprintf(args->errmsg, args->errmsg_len, - "%% Failure stopping ssmpingd for source %s: %d", - source_str, result); + snprintf( + args->errmsg, args->errmsg_len, + "%% Failure stopping ssmpingd for source %pPA: %d", + &source_addr, result); return NB_ERR_INCONSISTENCY; } diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index e43b46604c..da903bd980 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -30,8 +30,13 @@ #include "pim_ssmpingd.h" #include "pim_time.h" #include "pim_sock.h" +#include "network.h" +#if PIM_IPV == 4 static const char *const PIM_SSMPINGD_REPLY_GROUP = "232.43.211.234"; +#else +static const char *const PIM_SSMPINGD_REPLY_GROUP = "ff3e::4321:1234"; +#endif enum { PIM_SSMPINGD_REQUEST = 'Q', PIM_SSMPINGD_REPLY = 'A' }; @@ -43,7 +48,7 @@ void pim_ssmpingd_init(struct pim_instance *pim) assert(!pim->ssmpingd_list); - result = inet_pton(AF_INET, PIM_SSMPINGD_REPLY_GROUP, + result = inet_pton(PIM_AF, PIM_SSMPINGD_REPLY_GROUP, &pim->ssmpingd_group_addr); assert(result > 0); @@ -56,7 +61,7 @@ void pim_ssmpingd_destroy(struct pim_instance *pim) } static struct ssmpingd_sock *ssmpingd_find(struct pim_instance *pim, - struct in_addr source_addr) + pim_addr source_addr) { struct listnode *node; struct ssmpingd_sock *ss; @@ -65,7 +70,7 @@ static struct ssmpingd_sock *ssmpingd_find(struct pim_instance *pim, return 0; for (ALL_LIST_ELEMENTS_RO(pim->ssmpingd_list, node, ss)) - if (source_addr.s_addr == ss->source_addr.s_addr) + if (!pim_addr_cmp(source_addr, ss->source_addr)) return ss; return 0; @@ -76,83 +81,34 @@ static void ssmpingd_free(struct ssmpingd_sock *ss) XFREE(MTYPE_PIM_SSMPINGD, ss); } -static int ssmpingd_socket(struct in_addr addr, int port, int mttl) +#if PIM_IPV == 4 +static inline int ssmpingd_setsockopt(int fd, pim_addr addr, int mttl) { - struct sockaddr_in sockaddr; - int fd; - - fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (fd < 0) { - flog_err_sys(EC_LIB_SOCKET, - "%s: could not create socket: errno=%d: %s", - __func__, errno, safe_strerror(errno)); - return -1; - } - - sockaddr.sin_family = AF_INET; - sockaddr.sin_addr = addr; - sockaddr.sin_port = htons(port); - - if (bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_warn( - "%s: bind(fd=%d,addr=%s,port=%d,len=%zu) failure: errno=%d: %s", - __func__, fd, addr_str, port, sizeof(sockaddr), errno, - safe_strerror(errno)); - close(fd); - return -1; - } - /* Needed to obtain destination address from recvmsg() */ - { #if defined(HAVE_IP_PKTINFO) - /* Linux and Solaris IP_PKTINFO */ - int opt = 1; - if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt))) { - zlog_warn( - "%s: could not set IP_PKTINFO on socket fd=%d: errno=%d: %s", - __func__, fd, errno, safe_strerror(errno)); - } -#elif defined(HAVE_IP_RECVDSTADDR) - /* BSD IP_RECVDSTADDR */ - int opt = 1; - if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, - sizeof(opt))) { - zlog_warn( - "%s: could not set IP_RECVDSTADDR on socket fd=%d: errno=%d: %s", - __func__, fd, errno, safe_strerror(errno)); - } -#else - flog_err( - EC_LIB_DEVELOPMENT, - "%s %s: missing IP_PKTINFO and IP_RECVDSTADDR: unable to get dst addr from recvmsg()", - __FILE__, __func__); - close(fd); - return -1; -#endif - } - - { - int reuse = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, - sizeof(reuse))) { - zlog_warn( - "%s: could not set Reuse Address Option on socket fd=%d: errno=%d: %s", - __func__, fd, errno, safe_strerror(errno)); - close(fd); - return -1; - } - } - - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&mttl, - sizeof(mttl))) { + /* Linux and Solaris IP_PKTINFO */ + int opt = 1; + if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt))) { zlog_warn( - "%s: could not set multicast TTL=%d on socket fd=%d: errno=%d: %s", - __func__, mttl, fd, errno, safe_strerror(errno)); - close(fd); - return -1; + "%s: could not set IP_PKTINFO on socket fd=%d: errno=%d: %s", + __func__, fd, errno, safe_strerror(errno)); } +#elif defined(HAVE_IP_RECVDSTADDR) + /* BSD IP_RECVDSTADDR */ + int opt = 1; + if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt))) { + zlog_warn( + "%s: could not set IP_RECVDSTADDR on socket fd=%d: errno=%d: %s", + __func__, fd, errno, safe_strerror(errno)); + } +#else + flog_err( + EC_LIB_DEVELOPMENT, + "%s %s: missing IP_PKTINFO and IP_RECVDSTADDR: unable to get dst addr from recvmsg()", + __FILE__, __func__); + close(fd); + return -1; +#endif if (setsockopt_ipv4_multicast_loop(fd, 0)) { zlog_warn( @@ -171,25 +127,78 @@ static int ssmpingd_socket(struct in_addr addr, int port, int mttl) return -1; } - { - long flags; + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&mttl, + sizeof(mttl))) { + zlog_warn( + "%s: could not set multicast TTL=%d on socket fd=%d: errno=%d: %s", + __func__, mttl, fd, errno, safe_strerror(errno)); + close(fd); + return -1; + } - flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) { - zlog_warn( - "%s: could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", - __func__, fd, errno, safe_strerror(errno)); - close(fd); - return -1; - } + return 0; +} +#else +static inline int ssmpingd_setsockopt(int fd, pim_addr addr, int mttl) +{ + setsockopt_ipv6_pktinfo(fd, 1); + setsockopt_ipv6_multicast_hops(fd, mttl); - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { - zlog_warn( - "%s: could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", - __func__, fd, errno, safe_strerror(errno)); - close(fd); - return -1; - } + if (setsockopt_ipv6_multicast_loop(fd, 0)) { + zlog_warn( + "%s: could not disable Multicast Loopback Option on socket fd=%d: errno=%d: %s", + __func__, fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_LOOP; + } + + if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, (void *)&addr, + sizeof(addr))) { + zlog_warn( + "%s: could not set Outgoing Interface Option on socket fd=%d: errno=%d: %s", + __func__, fd, errno, safe_strerror(errno)); + close(fd); + return -1; + } + return 0; +} +#endif + + +static int ssmpingd_socket(pim_addr addr, int port, int mttl) +{ + struct sockaddr_storage sockaddr; + int fd; + int ret; + socklen_t len = sizeof(sockaddr); + + fd = socket(PIM_AF, SOCK_DGRAM, IPPROTO_UDP); + if (fd < 0) { + flog_err_sys(EC_LIB_SOCKET, + "%s: could not create socket: errno=%d: %s", + __func__, errno, safe_strerror(errno)); + return -1; + } + + pim_socket_getsockname(fd, (struct sockaddr *)&sockaddr, &len); + + if (bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) { + zlog_warn( + "%s: bind(fd=%d,addr=%pSUp,port=%d,len=%zu) failure: errno=%d: %s", + __func__, fd, &sockaddr, port, sizeof(sockaddr), errno, + safe_strerror(errno)); + close(fd); + return -1; + } + + set_nonblocking(fd); + sockopt_reuseaddr(fd); + + ret = ssmpingd_setsockopt(fd, addr, mttl); + if (ret) { + zlog_warn("ssmpingd_setsockopt failed"); + close(fd); + return -1; } return fd; @@ -202,12 +211,9 @@ static void ssmpingd_delete(struct ssmpingd_sock *ss) THREAD_OFF(ss->t_sock_read); if (close(ss->sock_fd)) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", ss->source_addr, source_str, - sizeof(source_str)); zlog_warn( - "%s: failure closing ssmpingd sock_fd=%d for source %s: errno=%d: %s", - __func__, ss->sock_fd, source_str, errno, + "%s: failure closing ssmpingd sock_fd=%d for source %pI4: errno=%d: %s", + __func__, ss->sock_fd, &ss->source_addr, errno, safe_strerror(errno)); /* warning only */ } @@ -217,7 +223,7 @@ static void ssmpingd_delete(struct ssmpingd_sock *ss) } static void ssmpingd_sendto(struct ssmpingd_sock *ss, const uint8_t *buf, - int len, struct sockaddr_in to) + int len, struct sockaddr_storage to) { socklen_t tolen = sizeof(to); int sent; @@ -225,18 +231,15 @@ static void ssmpingd_sendto(struct ssmpingd_sock *ss, const uint8_t *buf, sent = sendto(ss->sock_fd, buf, len, MSG_DONTWAIT, (struct sockaddr *)&to, tolen); if (sent != len) { - char to_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", to.sin_addr, to_str, sizeof(to_str)); if (sent < 0) { zlog_warn( - "%s: sendto() failure to %s,%d: fd=%d len=%d: errno=%d: %s", - __func__, to_str, ntohs(to.sin_port), - ss->sock_fd, len, errno, safe_strerror(errno)); + "%s: sendto() failure to %pSUp,fd=%d len=%d: errno=%d: %s", + __func__, &to, ss->sock_fd, len, errno, + safe_strerror(errno)); } else { zlog_warn( - "%s: sendto() partial to %s,%d: fd=%d len=%d: sent=%d", - __func__, to_str, ntohs(to.sin_port), - ss->sock_fd, len, sent); + "%s: sendto() partial to %pSUp, fd=%d len=%d: sent=%d", + __func__, &to, ss->sock_fd, len, sent); } } } @@ -285,14 +288,12 @@ static int ssmpingd_read_msg(struct ssmpingd_sock *ss) buf[0] = PIM_SSMPINGD_REPLY; - struct sockaddr_in *from_addr = (struct sockaddr_in *)&from; - /* unicast reply */ - ssmpingd_sendto(ss, buf, len, *from_addr); + ssmpingd_sendto(ss, buf, len, from); /* multicast reply */ - from_addr->sin_addr = ss->pim->ssmpingd_group_addr; - ssmpingd_sendto(ss, buf, len, *from_addr); + memcpy(&from, &ss->pim->ssmpingd_group_addr, sizeof(pim_addr)); + ssmpingd_sendto(ss, buf, len, from); return 0; } @@ -316,7 +317,7 @@ static void ssmpingd_read_on(struct ssmpingd_sock *ss) } static struct ssmpingd_sock *ssmpingd_new(struct pim_instance *pim, - struct in_addr source_addr) + pim_addr source_addr) { struct ssmpingd_sock *ss; int sock_fd; @@ -329,11 +330,8 @@ static struct ssmpingd_sock *ssmpingd_new(struct pim_instance *pim, sock_fd = ssmpingd_socket(source_addr, /* port: */ 4321, /* mTTL: */ 64); if (sock_fd < 0) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", source_addr, source_str, - sizeof(source_str)); - zlog_warn("%s: ssmpingd_socket() failure for source %s", - __func__, source_str); + zlog_warn("%s: ssmpingd_socket() failure for source %pI4", + __func__, &source_addr); return 0; } @@ -353,7 +351,7 @@ static struct ssmpingd_sock *ssmpingd_new(struct pim_instance *pim, return ss; } -int pim_ssmpingd_start(struct pim_instance *pim, struct in_addr source_addr) +int pim_ssmpingd_start(struct pim_instance *pim, pim_addr source_addr) { struct ssmpingd_sock *ss; @@ -364,47 +362,33 @@ int pim_ssmpingd_start(struct pim_instance *pim, struct in_addr source_addr) } { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", source_addr, source_str, - sizeof(source_str)); - zlog_info("%s: starting ssmpingd for source %s", __func__, - source_str); + zlog_info("%s: starting ssmpingd for source %pPAs", __func__, + &source_addr); } ss = ssmpingd_new(pim, source_addr); if (!ss) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", source_addr, source_str, - sizeof(source_str)); - zlog_warn("%s: ssmpingd_new() failure for source %s", __func__, - source_str); + zlog_warn("%s: ssmpingd_new() failure for source %pPAs", + __func__, &source_addr); return -1; } return 0; } -int pim_ssmpingd_stop(struct pim_instance *pim, struct in_addr source_addr) +int pim_ssmpingd_stop(struct pim_instance *pim, pim_addr source_addr) { struct ssmpingd_sock *ss; ss = ssmpingd_find(pim, source_addr); if (!ss) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", source_addr, source_str, - sizeof(source_str)); - zlog_warn("%s: could not find ssmpingd for source %s", __func__, - source_str); + zlog_warn("%s: could not find ssmpingd for source %pPAs", + __func__, &source_addr); return -1; } - { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", source_addr, source_str, - sizeof(source_str)); - zlog_info("%s: stopping ssmpingd for source %s", __func__, - source_str); - } + zlog_info("%s: stopping ssmpingd for source %pPAs", __func__, + &source_addr); ssmpingd_delete(ss); diff --git a/pimd/pim_ssmpingd.h b/pimd/pim_ssmpingd.h index fafdd7ade1..c4376bd0e4 100644 --- a/pimd/pim_ssmpingd.h +++ b/pimd/pim_ssmpingd.h @@ -31,14 +31,14 @@ struct ssmpingd_sock { int sock_fd; /* socket */ struct thread *t_sock_read; /* thread for reading socket */ - struct in_addr source_addr; /* source address */ + pim_addr source_addr; /* source address */ int64_t creation; /* timestamp of socket creation */ int64_t requests; /* counter */ }; void pim_ssmpingd_init(struct pim_instance *pim); void pim_ssmpingd_destroy(struct pim_instance *pim); -int pim_ssmpingd_start(struct pim_instance *pim, struct in_addr source_addr); -int pim_ssmpingd_stop(struct pim_instance *pim, struct in_addr source_addr); +int pim_ssmpingd_start(struct pim_instance *pim, pim_addr source_addr); +int pim_ssmpingd_stop(struct pim_instance *pim, pim_addr source_addr); #endif /* PIM_SSMPINGD_H */ diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 6de3a04b66..79deceee15 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -259,10 +259,8 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty) struct ssmpingd_sock *ss; ++writes; for (ALL_LIST_ELEMENTS_RO(pim->ssmpingd_list, node, ss)) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", ss->source_addr, source_str, - sizeof(source_str)); - vty_out(vty, "%sip ssmpingd %s\n", spaces, source_str); + vty_out(vty, "%sip ssmpingd %pI4\n", spaces, + &ss->source_addr); ++writes; } }