Skip to content

Commit

Permalink
[Utils] Add socket utility function.
Browse files Browse the repository at this point in the history
[Utils] Correct interface discovery algorithm for fedora builds.
  • Loading branch information
abh3 authored and gganis committed Nov 23, 2021
1 parent 3e1885f commit 1ceec9b
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 6 deletions.
61 changes: 55 additions & 6 deletions src/XrdNet/XrdNetUtils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ const char *XrdNetUtils::GetAddrs(std::vector<std::string> &hSVec,

const char *XrdNetUtils::GetAInfo(XrdNetSpace::hpSpec &aInfo)
{
struct addrinfo *xP = 0, *rP = 0, *nP;
struct addrinfo *last4 = 0, *last6 = 0, *xP = 0, *rP = 0, *nP;
unsigned short pNum = static_cast<unsigned short>(aInfo.port);

// Get all of the addresses
Expand All @@ -367,25 +367,31 @@ const char *XrdNetUtils::GetAInfo(XrdNetSpace::hpSpec &aInfo)
return (rc ? gai_strerror(rc) : "host not found");
}

// Count the number of entries we will return and chain the entries
// Count the number of entries we will return and chain the entries. We will
// never return link local addresses which may be returned (shouldn't but does)
//
do {nP = rP->ai_next;
if (rP->ai_family == AF_INET6 || rP->ai_family == AF_INET)
{SIN_PORT(rP) = pNum;
bool v4mapped = false;
if (rP->ai_family == AF_INET6)
{struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)rP->ai_addr;
if (IN6_IS_ADDR_LINKLOCAL(&ipv6->sin6_addr))
{rP->ai_next = xP; xP = rP; continue;}
v4mapped = IN6_IS_ADDR_V4MAPPED(&ipv6->sin6_addr);
}
if (aInfo.noOrder || rP->ai_family == AF_INET || v4mapped)
{rP->ai_next = aInfo.aiP4;
aInfo.aiP4 = rP;
{if (last4) last4->ai_next = rP;
else aInfo.aiP4 = rP;
last4 = rP;
aInfo.aNum4++;
} else {
rP->ai_next = aInfo.aiP6;
aInfo.aiP6 = rP;
if (last6) last6->ai_next = rP;
else aInfo.aiP6 = rP;
last6 = rP;
aInfo.aNum6++;
}
rP->ai_next = 0;
} else {rP->ai_next = xP; xP = rP;}
} while((rP = nP));

Expand Down Expand Up @@ -482,6 +488,49 @@ const char *XrdNetUtils::GetHostPort(XrdNetSpace::hpSpec &aInfo,
return 0;
}

/******************************************************************************/
/* g e t S o k I n f o */
/******************************************************************************/

int XrdNetUtils::GetSokInfo(int fd, char *theAddr, int theALen, char &theType)
{
XrdNetSockAddr theIP;
XrdNetAddr ipAddr;
static const int fmtopts = XrdNetAddrInfo::noPortRaw
| XrdNetAddrInfo::prefipv4;
SOCKLEN_t addrSize = sizeof(theIP);
int rc;
unsigned short thePort;

// The the address wanted
//
rc = (fd > 0 ? getpeername( fd, &theIP.Addr, &addrSize)
: getsockname(-fd, &theIP.Addr, &addrSize));
if (rc) return -errno;

// Set the address
//
if (ipAddr.Set(&theIP.Addr)) return -EAFNOSUPPORT;

// Establis the type of address we have
//
if (ipAddr.isIPType(XrdNetAddrInfo::IPv4) || ipAddr.isMapped()) theType='4';
else theType = '6';

// Now format the address
//
if (theAddr && theALen > 0
&& !ipAddr.Format(theAddr, theALen, XrdNetAddrInfo::fmtAddr, fmtopts))
return -EINVAL;

// Get the port number and return it.
//
thePort = htons((theIP.Addr.sa_family == AF_INET
? theIP.v4.sin_port : theIP.v6.sin6_port));
return static_cast<int>(thePort);
}


/******************************************************************************/
/* H o s t s */
/******************************************************************************/
Expand Down
24 changes: 24 additions & 0 deletions src/XrdNet/XrdNetUtils.hh
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,30 @@ const char *GetAddrs(std::vector<std::string> &hSVec,
int *ordn=0, AddrOpts opts=allIPMap,
unsigned int rotNum=0, bool force=false);

//------------------------------------------------------------------------------
//! Obtain connection information from a socket.
//!
//! @param fd The file descriptor of the socket whose address is to be
//! converted. The sign of the fd indicates which address:
//! fd > 0 the peer address is used (i.e. getpeername)
//! fd < 0 the local address is used (i.e. getsockname)
//! @param theAddr pointer to a buffer of theAlen bytes where the text
//! version of the IP address is to be returned. The text
//! uses the actual native address format. If theAddr is
//! nil or theAlen is not positive, only the port and
//! address type are returned.
//! @param theALen length of the theAddr buffer.
//! @param theType either the character 4 (IPv4) or 6 (IPv6) is returned.
//! corrresponding to the address family. Note that should
//! be AF_INET6 but the address is mapped, '4' is returned.
//!
//! @return Success: >= 0 corresponding to the port number.
//! @return Failure: < 0 corresponding to -errno.
//------------------------------------------------------------------------------

static
int GetSokInfo(int fd, char *theAddr, int theALen, char &theType);

//------------------------------------------------------------------------------
//! Obtain an easily digestable list of hosts. This is the list of up to eight
//! unique aliases (i.e. with different addresses) assigned to a base hostname.
Expand Down

0 comments on commit 1ceec9b

Please sign in to comment.