summaryrefslogtreecommitdiff
path: root/pimd/pim_pim.c
diff options
context:
space:
mode:
authorBalaji Gurudoss <G_Balaji1@dell.com>2022-04-27 19:19:43 +0530
committerBalaji Gurudoss <G_Balaji1@dell.com>2022-06-13 16:51:01 +0530
commit529f52252ca6d93ac05c9b1fa2575b7e6f2aa761 (patch)
tree9263d3b35b64978f6658b56182423035e3c30073 /pimd/pim_pim.c
parentdb28205528db7b67c53c437c4a0c8f52f492225e (diff)
pim6d: Removal of IPV6_HDRINCL option
1. Removal of IPV6_HDRINCL option 2. Removal of IPv6 headers in TX 3. Addition of IPV6_PKTINFO and setting of source ipv6 address for TX. Signed-off-by: Balaji Gurudoss <G_Balaji1@dell.com>
Diffstat (limited to 'pimd/pim_pim.c')
-rw-r--r--pimd/pim_pim.c100
1 files changed, 75 insertions, 25 deletions
diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c
index f0f4a7139b..1dd99d7ecd 100644
--- a/pimd/pim_pim.c
+++ b/pimd/pim_pim.c
@@ -42,6 +42,7 @@
#include "pim_register.h"
#include "pim_errors.h"
#include "pim_bsm.h"
+#include <lib/lib_errors.h>
static void on_pim_hello_send(struct thread *t);
@@ -551,6 +552,7 @@ void pim_sock_reset(struct interface *ifp)
static uint16_t ip_id = 0;
#endif
+#if PIM_IPV == 4
static int pim_msg_send_frame(int fd, char *buf, size_t len,
struct sockaddr *dst, size_t salen,
const char *ifname)
@@ -558,7 +560,6 @@ static int pim_msg_send_frame(int fd, char *buf, size_t len,
if (sendto(fd, buf, len, MSG_DONTWAIT, dst, salen) >= 0)
return 0;
-#if PIM_IPV == 4
if (errno == EMSGSIZE) {
struct ip *ip = (struct ip *)buf;
size_t hdrsize = sizeof(struct ip);
@@ -585,7 +586,6 @@ static int pim_msg_send_frame(int fd, char *buf, size_t len,
return pim_msg_send_frame(fd, (char *)ip2, sendlen, dst, salen,
ifname);
}
-#endif
zlog_warn(
"%s: sendto() failure to %pSU: iface=%s fd=%d msg_size=%zd: %m",
@@ -593,16 +593,65 @@ static int pim_msg_send_frame(int fd, char *buf, size_t len,
return -1;
}
+#else
+static int pim_msg_send_frame(pim_addr src, pim_addr dst, ifindex_t ifindex,
+ struct iovec *message, int fd)
+{
+ int retval;
+ struct msghdr smsghdr = {};
+ struct cmsghdr *scmsgp;
+ union cmsgbuf {
+ struct cmsghdr hdr;
+ uint8_t buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
+ };
+ struct in6_pktinfo *pktinfo;
+ struct sockaddr_in6 dst_sin6 = {};
+
+ union cmsgbuf cmsg_buf = {};
+
+ /* destination address */
+ dst_sin6.sin6_family = AF_INET6;
+#ifdef SIN6_LEN
+ dst_sin6.sin6_len = sizeof(struct sockaddr_in6);
+#endif /*SIN6_LEN*/
+ dst_sin6.sin6_addr = dst;
+ dst_sin6.sin6_scope_id = ifindex;
+
+ /* send msg hdr */
+ smsghdr.msg_iov = message;
+ smsghdr.msg_iovlen = 1;
+ smsghdr.msg_name = (caddr_t)&dst_sin6;
+ smsghdr.msg_namelen = sizeof(dst_sin6);
+ smsghdr.msg_control = (caddr_t)&cmsg_buf.buf;
+ smsghdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
+ smsghdr.msg_flags = 0;
+
+ scmsgp = CMSG_FIRSTHDR(&smsghdr);
+ scmsgp->cmsg_level = IPPROTO_IPV6;
+ scmsgp->cmsg_type = IPV6_PKTINFO;
+ scmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+
+ pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp));
+ pktinfo->ipi6_ifindex = ifindex;
+ pktinfo->ipi6_addr = src;
+
+ retval = sendmsg(fd, &smsghdr, 0);
+ if (retval < 0)
+ flog_err(
+ EC_LIB_SOCKET,
+ "sendmsg failed: source: %pI6 Dest: %pI6 ifindex: %d: %s (%d)",
+ &src, &dst, ifindex, safe_strerror(errno), errno);
+
+ return retval;
+}
+#endif
+
int pim_msg_send(int fd, pim_addr src, pim_addr dst, uint8_t *pim_msg,
int pim_msg_size, struct interface *ifp)
{
- socklen_t tolen;
- unsigned char buffer[10000];
- unsigned char *msg_start;
- uint8_t ttl;
- struct pim_msg_header *header;
struct pim_interface *pim_ifp;
+
pim_ifp = ifp->info;
if (pim_ifp->pim_passive_enable) {
@@ -613,9 +662,15 @@ int pim_msg_send(int fd, pim_addr src, pim_addr dst, uint8_t *pim_msg,
return 0;
}
+#if PIM_IPV == 4
+ uint8_t ttl;
+ struct pim_msg_header *header;
+ unsigned char buffer[10000];
+
memset(buffer, 0, 10000);
header = (struct pim_msg_header *)pim_msg;
+
/*
* Omnios apparently doesn't have a #define for IP default
* ttl that is the same as all other platforms.
@@ -643,10 +698,11 @@ int pim_msg_send(int fd, pim_addr src, pim_addr dst, uint8_t *pim_msg,
break;
}
-#if PIM_IPV == 4
struct ip *ip = (struct ip *)buffer;
struct sockaddr_in to = {};
int sendlen = sizeof(*ip) + pim_msg_size;
+ socklen_t tolen;
+ unsigned char *msg_start;
ip->ip_id = htons(++ip_id);
ip->ip_hl = 5;
@@ -661,23 +717,6 @@ int pim_msg_send(int fd, pim_addr src, pim_addr dst, uint8_t *pim_msg,
to.sin_family = AF_INET;
to.sin_addr = dst;
tolen = sizeof(to);
-#else
- struct ip6_hdr *ip = (struct ip6_hdr *)buffer;
- struct sockaddr_in6 to = {};
- int sendlen = sizeof(*ip) + pim_msg_size;
-
- ip->ip6_flow = 0;
- ip->ip6_vfc = (6 << 4) | (IPTOS_PREC_INTERNETCONTROL >> 4);
- ip->ip6_plen = htons(pim_msg_size);
- ip->ip6_nxt = PIM_IP_PROTO_PIM;
- ip->ip6_hlim = ttl;
- ip->ip6_src = src;
- ip->ip6_dst = dst;
-
- to.sin6_family = AF_INET6;
- to.sin6_addr = dst;
- tolen = sizeof(to);
-#endif
msg_start = buffer + sizeof(*ip);
memcpy(msg_start, pim_msg, pim_msg_size);
@@ -694,6 +733,17 @@ int pim_msg_send(int fd, pim_addr src, pim_addr dst, uint8_t *pim_msg,
pim_msg_send_frame(fd, (char *)buffer, sendlen, (struct sockaddr *)&to,
tolen, ifp->name);
return 0;
+
+#else
+ struct iovec iovector[2];
+
+ iovector[0].iov_base = pim_msg;
+ iovector[0].iov_len = pim_msg_size;
+
+ pim_msg_send_frame(src, dst, ifp->ifindex, &iovector[0], fd);
+
+ return 0;
+#endif
}
static int hello_send(struct interface *ifp, uint16_t holdtime)