#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