From e35356af91b72da7f4e7fe03c43babb51e369bc0 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH] ripd: switch from sendto() to sendmsg() For unknown reasons, the IP_MULTICAST_IF sockoption doesn't seem to work when the given socket is bound to a VRF device on Linux. Switch from sendto() to sendmsg() so that we can specify the outgoing interface of multicast packets using IP_PKTINFO ancillary data. This also makes ripd more consistent with ripngd, which also uses sendmsg() to send packets on the wire. Signed-off-by: Renato Westphal --- ripd/ripd.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/ripd/ripd.c b/ripd/ripd.c index 6b9c5fe886..916fba2269 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -1386,6 +1386,13 @@ static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to, struct rip *rip; int ret; struct sockaddr_in sin; + struct msghdr msg; + struct iovec iov; +#ifdef GNU_LINUX + struct cmsghdr *cmsgptr; + char adata[256] = {}; + struct in_pktinfo *pkt; +#endif /* GNU_LINUX */ assert(ifc != NULL); ri = ifc->ifp->info; @@ -1448,8 +1455,27 @@ static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to, rip_interface_multicast_set(rip->sock, ifc); } - ret = sendto(rip->sock, buf, size, 0, (struct sockaddr *)&sin, - sizeof(struct sockaddr_in)); + memset(&msg, 0, sizeof(msg)); + msg.msg_name = (void *)&sin; + msg.msg_namelen = sizeof(struct sockaddr_in); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + iov.iov_base = buf; + iov.iov_len = size; + +#ifdef GNU_LINUX + msg.msg_control = (void *)adata; + msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); + + cmsgptr = (struct cmsghdr *)adata; + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + cmsgptr->cmsg_level = IPPROTO_IP; + cmsgptr->cmsg_type = IP_PKTINFO; + pkt = (struct in_pktinfo *)CMSG_DATA(cmsgptr); + pkt->ipi_ifindex = ifc->ifp->ifindex; +#endif /* GNU_LINUX */ + + ret = sendmsg(rip->sock, &msg, 0); if (IS_RIP_DEBUG_EVENT) zlog_debug("SEND to %s.%d", inet_ntoa(sin.sin_addr), -- 2.39.5