#ifndef __XRDNETADDRINFO_HH__
#define __XRDNETADDRINFO_HH__
/******************************************************************************/
/* */
/* X r d N e t A d d r I n f o . h h */
/* */
/* (c) 2013 by the Board of Trustees of the Leland Stanford, Jr., University */
/* All Rights Reserved */
/* Produced by Andrew Hanushevsky for Stanford University under contract */
/* DE-AC02-76-SFO0515 with the Department of Energy */
/* */
/* This file is part of the XRootD software suite. */
/* */
/* XRootD is free software: you can redistribute it and/or modify it under */
/* the terms of the GNU Lesser General Public License as published by the */
/* Free Software Foundation, either version 3 of the License, or (at your */
/* option) any later version. */
/* */
/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public License */
/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
/* COPYING (GPL license). If not, see . */
/* */
/* The copyright holder's institutional names and contributor's names may not */
/* be used to endorse or promote products derived from this software without */
/* specific prior written permission of the institution or contributor. */
/******************************************************************************/
#include
#include
#include
#include
#include
#include
#include "XrdNet/XrdNetSockAddr.hh"
#include "XrdSys/XrdSysPlatform.hh"
//------------------------------------------------------------------------------
//! The XrdNetAddrInfo class is meant to provide read/only access to members
//! that only class XrdNetAddr can manipulate. This allows the generic use of
//! the XrdNetAddr class but provides a means of exporting that information to
//! other objects without allowing those objects to modify the information.
//------------------------------------------------------------------------------
struct addrinfo;
class XrdNetCache;
class XrdNetAddrInfo
{
public:
//------------------------------------------------------------------------------
//! Provide the protocol languag being spoken (e.g. xroot, http, etc).
//!
//! @return Pointer to the protocol language being used. If unknown, nil ia
//! returned. Use the isUsingTLS() method to see if a secure version of
//! the protocol is being used.
//------------------------------------------------------------------------------
const char *Dialect() {return protName;}
//------------------------------------------------------------------------------
//! Provide our address family.
//!
//! @return Success: Returns AF_INET, AF_INET6, or AF_UNIX.
//! Failure: Returns 0, address is not valid.
//------------------------------------------------------------------------------
int Family() const {return static_cast(IP.Addr.sa_family);}
//------------------------------------------------------------------------------
//! Format our address into a supplied buffer with one of the following layouts
//! (the ':' or ':/path' can be omitted if desired, see fmtOpts param):
//! IP.xx: host_name:
//! IP.v4: a.b.c.d:
//! IP.4to6: [::ffff:a.b.c.d]: | [::a.b.c.d]:
//! IP.v6: [a:b:c:d:e:f:g:h]:
//! IP.Unix: localhost:/
//!
//! @param bAddr address of buffer for result
//! @param bLen length of buffer
//! @param fmtType specifies the type of format desired via fmtUse enum.
//! @param fmtOpts additional formatting options (can be or'd):
//! noPort - do not append the port number to the address.
//! noPortRaw - no port and no brackets for IPv6.
//! old6Map4 - use deprecated IPV6 mapped format '[::x.x.x.x]'
//!
//! @return Success: The number of characters (less null) in Buff.
//! @return Failure: 0 (buffer is too small or not a valid address). However,
//! if bLen > 0 the buffer will contain a null terminated
//! string of up to 8 question marks.
//------------------------------------------------------------------------------
enum fmtUse {fmtAuto=0, //!< Hostname if already resolved o/w use fmtAddr
fmtName, //!< Hostname if it is resolvable o/w use fmtAddr
fmtAddr, //!< Address using suitable ipv4 or ipv6 format
fmtAdv6}; //!< Address only in ipv6 format
static const int noPort = 0x0000001; //!< Do not add port number
static const int noPortRaw = 0x0000002; //!< Use raw address format (no port)
static const int old6Map4 = 0x0000004; //!< Use deprecated IPV6 mapped format
static const int prefipv4 = 0x0000008; //!< Use if mapped IPV4 actual format
int Format(char *bAddr, int bLen, fmtUse fmtType=fmtAuto, int fmtOpts=0);
//------------------------------------------------------------------------------
//! Indicate whether or not our address is the loopback address. Use this
//! method to gaurd against UDP packet spoofing.
//!
//! @return True: This is the loopback address.
//! @return False: This is not the loopback address.
//------------------------------------------------------------------------------
bool isLoopback();
//------------------------------------------------------------------------------
//! Indicate whether or not a string is a possible hostname and not IP address.
//! The return value does not aimply any kind of validity. For instance, a
//! false return indicates this is not a valid hostname does not mean it is
//! a valid IP address.
//!
//! @param name The string to check.
//!
//! @return True: This is a possible hostname (i.e. not IP address).
//! @return False: This is not a possible hostname.
//------------------------------------------------------------------------------
static bool isHostName(const char *name);
//------------------------------------------------------------------------------
//! Indicate whether or not our address is if the desired type.
//!
//! @param ipType The IP address version to test (see enum below).
//!
//! @return True: This is the address version of ipType.
//! @return False: This is not the address version of ipType.
//------------------------------------------------------------------------------
enum IPType {IPv4 = AF_INET, IPv6 = AF_INET6, IPuX = AF_UNIX};
bool isIPType(IPType ipType) const {return IP.Addr.sa_family == ipType;}
//------------------------------------------------------------------------------
//! Indicate whether or not our address is an IPv4 mapped to IPv6 address.
//!
//! @return True: The address is a mapped IPv4 address.
//! False: The address is not a mapped IPv4 address.
//------------------------------------------------------------------------------
bool isMapped() const {return IP.Addr.sa_family == AF_INET6
&& IN6_IS_ADDR_V4MAPPED(&IP.v6.sin6_addr);
}
//------------------------------------------------------------------------------
//! Indicate whether or not our address is private.
//!
//! @return True: This address is private.
//! False: This address is not private.
//------------------------------------------------------------------------------
bool isPrivate();
//------------------------------------------------------------------------------
//! Indicate whether or not our address is registered in the DNS.
//!
//! @return True: This address is registered.
//! False: This address is not registered.
//------------------------------------------------------------------------------
bool isRegistered();
//------------------------------------------------------------------------------
//! Indicate whether or not the endpoint is using TLS for communications.
//!
//! @return True: This address is using TLS.
//! False: This address is not using TLS.
//------------------------------------------------------------------------------
bool isUsingTLS();
//------------------------------------------------------------------------------
//! Obtain the location of this address.
//!
//! @return !0 pointer to the unverified location information. Not all
//! fields may be set.
//! @return =0 location information is not available.
//------------------------------------------------------------------------------
struct LocInfo
{unsigned char Country[2]; //!< Two letter TLD country code
unsigned char Region; //!< Region (may combine adjacent countries)
unsigned char Locale; //!< Locale (may combine adjacent regions)
char TimeZone; //!< +/- hours from GMT (-128 if not set)
char Flags; //!< Flags
short Speed; //!< I/F speed (Gb*1024/100)(not supported)
int Latitude; //!< Degrees +/- xx.xxxxxx (not supported)
int Longtitude; //!< Degrees +/- xx.xxxxxx (not supported)
LocInfo() : Region(0), Locale(0), TimeZone(-128), Flags(0),
Speed(0), Latitude(0), Longtitude(0) {*Country = 0;}
};
const struct
LocInfo *Location() {return (addrLoc.Country[0] ? &addrLoc : 0);}
//------------------------------------------------------------------------------
//! Convert our IP address to the corresponding [host] name.
//!
//! @param eName value to return when the name cannot be determined.
//! @param eText when not null, the reason for a failure is returned.
//!
//! @return Success: Pointer to the name or ip address with eText, if supplied,
//! set to zero. The memory is owned by the object and is
//! deleted when the object is deleted or Set() is called.
//! Failure: eName param and if eText is not zero, returns a pointer
//! to a message describing the reason for the failure. The
//! message is in persistent storage and cannot be modified.
//------------------------------------------------------------------------------
const char *Name(const char *eName=0, const char **eText=0);
//------------------------------------------------------------------------------
//! Provide a pointer to our socket address suitable for use in calls to methods
//! that require our internal format of sock addr. A value is only returned for
//! IPV6/4 addresses and is nill otherwise. The pointer refers to memory
//! allocated by this object and becomes invalid should the object be deleted.
//! Use SockSize() to get its logical length.
//------------------------------------------------------------------------------
const
XrdNetSockAddr *NetAddr() {return (sockAddr == (void *)&IP ? &IP : 0);}
//------------------------------------------------------------------------------
//! Return the port number for our address.
//!
//! @return Success: The port number, which may be 0 if not set.
//! Failure: -1 address is not an internet address or port is invalid.
//------------------------------------------------------------------------------
int Port();
//------------------------------------------------------------------------------
//! Provide our protocol family.
//!
//! @return Success: Returns PF_INET, PF_INET6, or PF_UNIX.
//! Failure: Returns 0, address is not valid.
//------------------------------------------------------------------------------
int Protocol() {return static_cast(protType);}
//------------------------------------------------------------------------------
//! Check if the IP address in this object is the same as the one passed.
//!
//! @param ipAddr points to the network address object to compare.
//! @param plusPort when true, port values must also match. In any case, both
//! addresses must be of the same address family.
//!
//! @return Success: True (addresses are the same).
//! Failure: False (addresses are not the same).
//!
//! Note: implemented in terms of const version
//------------------------------------------------------------------------------
int Same(const XrdNetAddrInfo *ipAddr, bool plusPort=false);
//------------------------------------------------------------------------------
//! Provide a pointer to our socket address suitable for use in calls to
//! functions that require one (e.g. bind() etc). The pointer refers to memory
//! allocated by this object and becomes invalid should the object be deleted
//! or when Set() is called. Use SockSize() to get its length.
//------------------------------------------------------------------------------
const
sockaddr *SockAddr() {return sockAddr;}
//------------------------------------------------------------------------------
//! Provide the length of our socket adress. Useful for system calls needing it.
//!
//! @return Success: Returns the length of the address returned by SockAddr().
//! Failure: Returns 0, address is not valid.
//------------------------------------------------------------------------------
SOCKLEN_t SockSize() {return static_cast(addrSize);}
//------------------------------------------------------------------------------
//! Get the associated file descriptor.
//!
//! @return The associated file descriptor. If negative, no association exists.
//------------------------------------------------------------------------------
int SockFD() {return (sockNum ? sockNum : -1);}
//------------------------------------------------------------------------------
//! Assignment operator
//------------------------------------------------------------------------------
XrdNetAddrInfo &operator=(XrdNetAddrInfo const &rhs)
{if (&rhs != this)
{memmove(&IP, &rhs.IP, sizeof(IP));
addrSize = rhs.addrSize; sockNum = rhs.sockNum;
protType = rhs.protType;
protFlgs = rhs.protFlgs;
protName = rhs.protName;
if (hostName) free(hostName);
hostName = (rhs.hostName ? strdup(rhs.hostName):0);
addrLoc = rhs.addrLoc;
if (rhs.sockAddr != &rhs.IP.Addr)
{if (!unixPipe || sockAddr == &IP.Addr)
unixPipe = new sockaddr_un;
memcpy(unixPipe, rhs.unixPipe, sizeof(sockaddr_un));
} else sockAddr = &IP.Addr;
}
return *this;
}
//------------------------------------------------------------------------------
//! Copy constructor
//------------------------------------------------------------------------------
XrdNetAddrInfo(XrdNetAddrInfo const &oP)
{hostName = 0;
unixPipe = 0;
*this = oP;
}
//------------------------------------------------------------------------------
//! Constructor
//------------------------------------------------------------------------------
XrdNetAddrInfo() : hostName(0), addrSize(0), protType(0),
protFlgs(0), sockNum(0), protName(0)
{IP.Addr.sa_family = 0;
sockAddr = &IP.Addr;
}
XrdNetAddrInfo(const XrdNetAddrInfo *addr) : hostName(0) {*this = *addr;}
//------------------------------------------------------------------------------
//! Destructor
//------------------------------------------------------------------------------
~XrdNetAddrInfo() {if (hostName) free(hostName);
if (sockAddr != &IP.Addr) delete unixPipe;
}
protected:
char *LowCase(char *str);
int QFill(char *bAddr, int bLen);
int Resolve();
static XrdNetCache *dnsCache;
XrdNetSockAddr IP;
union {struct sockaddr *sockAddr;
struct sockaddr_un *unixPipe;
};
char *hostName;
LocInfo addrLoc;
unsigned short addrSize;
unsigned char protType;
unsigned char protFlgs;
int sockNum;
const char *protName;
// Flag settings in protFlgs
//
static const char isTLS = 0x01; //!< Location using TLS
};
#endif