Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions iocore/net/P_UDPPacket.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,14 +225,15 @@ new_UDPPacket(ink_hrtime when, Ptr<IOBufferBlock> buf)
}

TS_INLINE UDPPacket *
new_incoming_UDPPacket(struct sockaddr *from, char *buf, int len)
new_incoming_UDPPacket(struct sockaddr *from, struct sockaddr *to, char *buf, int len)
{
UDPPacketInternal *p = udpPacketAllocator.alloc();

p->in_the_priority_queue = 0;
p->in_heap = 0;
p->delivery_time = 0;
ats_ip_copy(&p->from, from);
ats_ip_copy(&p->to, to);

IOBufferBlock *body = new_IOBufferBlock();
body->alloc(iobuffer_size_to_index(len));
Expand All @@ -244,14 +245,15 @@ new_incoming_UDPPacket(struct sockaddr *from, char *buf, int len)
}

TS_INLINE UDPPacket *
new_incoming_UDPPacket(struct sockaddr *from, Ptr<IOBufferBlock> &block)
new_incoming_UDPPacket(struct sockaddr *from, struct sockaddr *to, Ptr<IOBufferBlock> &block)
{
UDPPacketInternal *p = udpPacketAllocator.alloc();

p->in_the_priority_queue = 0;
p->in_heap = 0;
p->delivery_time = 0;
ats_ip_copy(&p->from, from);
ats_ip_copy(&p->to, to);
p->chain = block;

return p;
Expand Down
122 changes: 118 additions & 4 deletions iocore/net/UnixUDPNet.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@

****************************************************************************/

#if defined(darwin)
/* This is for IPV6_PKTINFO and IPV6_RECVPKTINFO */
#define __APPLE_USE_RFC_3542
#endif

#include "P_Net.h"
#include "P_UDPNet.h"

Expand Down Expand Up @@ -162,12 +167,15 @@ UDPNetProcessorInternal::udp_read_from_net(UDPNetHandler *nh, UDPConnection *xuc

// build struct msghdr
sockaddr_in6 fromaddr;
sockaddr_in6 toaddr;
int toaddr_len = sizeof(toaddr);
char *cbuf[1024];
msg.msg_name = &fromaddr;
msg.msg_namelen = sizeof(fromaddr);
msg.msg_iov = tiovec;
msg.msg_iovlen = niov;
msg.msg_control = nullptr;
msg.msg_controllen = 0;
msg.msg_control = cbuf;
msg.msg_controllen = sizeof(cbuf);

// receive data by recvmsg
r = socketManager.recvmsg(uc->getFd(), &msg, 0);
Expand Down Expand Up @@ -197,8 +205,38 @@ UDPNetProcessorInternal::udp_read_from_net(UDPNetHandler *nh, UDPConnection *xuc
}
}

safe_getsockname(xuc->getFd(), reinterpret_cast<struct sockaddr *>(&toaddr), &toaddr_len);
for (auto cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
switch (cmsg->cmsg_type) {
#ifdef IP_PKTINFO
case IP_PKTINFO:
if (cmsg->cmsg_level == IPPROTO_IP) {
struct in_pktinfo *pktinfo = reinterpret_cast<struct in_pktinfo *>(CMSG_DATA(cmsg));
reinterpret_cast<sockaddr_in *>(&toaddr)->sin_addr.s_addr = pktinfo->ipi_addr.s_addr;
}
break;
#endif
#ifdef IP_RECVDSTADDR
case IP_RECVDSTADDR:
if (cmsg->cmsg_level == IPPROTO_IP) {
struct in_addr *addr = reinterpret_cast<struct in_addr *>(CMSG_DATA(cmsg));
reinterpret_cast<sockaddr_in *>(&toaddr)->sin_addr.s_addr = addr->s_addr;
}
break;
#endif
#if defined(IPV6_PKTINFO) || defined(IPV6_RECVPKTINFO)
case IPV6_PKTINFO: // IPV6_RECVPKTINFO uses IPV6_PKTINFO too
if (cmsg->cmsg_level == IPPROTO_IPV6) {
struct in6_pktinfo *pktinfo = reinterpret_cast<struct in6_pktinfo *>(CMSG_DATA(cmsg));
memcpy(toaddr.sin6_addr.s6_addr, &pktinfo->ipi6_addr, 16);
}
break;
#endif
}
}

// create packet
UDPPacket *p = new_incoming_UDPPacket(ats_ip_sa_cast(&fromaddr), chain);
UDPPacket *p = new_incoming_UDPPacket(ats_ip_sa_cast(&fromaddr), ats_ip_sa_cast(&toaddr), chain);
p->setConnection(uc);
// queue onto the UDPConnection
uc->inQueue.push((UDPPacketInternal *)p);
Expand Down Expand Up @@ -628,6 +666,42 @@ UDPNetProcessor::CreateUDPSocket(int *resfd, sockaddr const *remote_addr, Action
}
}

if (opt.ip_family == AF_INET) {
bool succeeded = false;
int enable = 1;
#ifdef IP_PKTINFO
if ((res = safe_setsockopt(fd, IPPROTO_IP, IP_PKTINFO, reinterpret_cast<char *>(&enable), sizeof(enable))) == 0) {
succeeded = true;
}
#endif
#ifdef IP_RECVDSTADDR
if ((res = safe_setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, reinterpret_cast<char *>(&enable), sizeof(enable))) == 0) {
succeeded = true;
}
#endif
if (!succeeded) {
Debug("udpnet", "setsockeopt for pktinfo failed");
goto HardError;
}
} else if (opt.ip_family == AF_INET6) {
bool succeeded = false;
int enable = 1;
#ifdef IPV6_PKTINFO
if ((res = safe_setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, reinterpret_cast<char *>(&enable), sizeof(enable))) == 0) {
succeeded = true;
}
#endif
#ifdef IPV6_RECVPKTINFO
if ((res = safe_setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, reinterpret_cast<char *>(&enable), sizeof(enable))) == 0) {
succeeded = true;
}
#endif
if (!succeeded) {
Debug("udpnet", "setsockeopt for pktinfo failed");
goto HardError;
}
}

if (local_addr.port() || !is_any_address) {
if (-1 == socketManager.ink_bind(fd, &local_addr.sa, ats_ip_size(&local_addr.sa))) {
char buff[INET6_ADDRPORTSTRLEN];
Expand Down Expand Up @@ -683,6 +757,42 @@ UDPNetProcessor::UDPBind(Continuation *cont, sockaddr const *addr, int send_bufs
goto Lerror;
}

if (addr->sa_family == AF_INET) {
bool succeeded = false;
int enable = 1;
#ifdef IP_PKTINFO
if ((res = safe_setsockopt(fd, IPPROTO_IP, IP_PKTINFO, reinterpret_cast<char *>(&enable), sizeof(enable))) == 0) {
succeeded = true;
}
#endif
#ifdef IP_RECVDSTADDR
if ((res = safe_setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, reinterpret_cast<char *>(&enable), sizeof(enable))) == 0) {
succeeded = true;
}
#endif
if (!succeeded) {
Debug("udpnet", "setsockeopt for pktinfo failed");
goto Lerror;
}
} else if (addr->sa_family == AF_INET6) {
bool succeeded = false;
int enable = 1;
#ifdef IPV6_PKTINFO
if ((res = safe_setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, reinterpret_cast<char *>(&enable), sizeof(enable))) == 0) {
succeeded = true;
}
#endif
#ifdef IPV6_RECVPKTINFO
if ((res = safe_setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, reinterpret_cast<char *>(&enable), sizeof(enable))) == 0) {
succeeded = true;
}
#endif
if (!succeeded) {
Debug("udpnet", "setsockeopt for pktinfo failed");
goto Lerror;
}
}

// If this is a class D address (i.e. multicast address), use REUSEADDR.
if (ats_is_ip_multicast(addr)) {
int enable_reuseaddr = 1;
Expand All @@ -692,6 +802,10 @@ UDPNetProcessor::UDPBind(Continuation *cont, sockaddr const *addr, int send_bufs
}
}

if (ats_is_ip6(addr) && (res = safe_setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, SOCKOPT_ON, sizeof(int))) < 0) {
goto Lerror;
}

if ((res = socketManager.ink_bind(fd, addr, ats_ip_size(addr))) < 0) {
goto Lerror;
}
Expand Down Expand Up @@ -858,7 +972,7 @@ UDPQueue::SendUDPPacket(UDPPacketInternal *p, int32_t /* pktLen ATS_UNUSED */)
msg.msg_flags = 0;
#endif
msg.msg_name = (caddr_t)&p->to.sa;
msg.msg_namelen = sizeof(p->to.sa);
msg.msg_namelen = ats_ip_size(p->to);
iov_len = 0;

for (IOBufferBlock *b = p->chain.get(); b != nullptr; b = b->next.get()) {
Expand Down