#ifndef __XRDNETIF_HH__ #define __XRDNETIF_HH__ /******************************************************************************/ /* */ /* X r d N e t I F . 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 //------------------------------------------------------------------------------ //! The XrdNetIF class handles host interfaces. It is used to obtain the //! available interface addresses, encode them to be easily transmitted, and //! decode them to set the interface variations that can be used. //------------------------------------------------------------------------------ class XrdNetAddrInfo; class XrdOucTList; class XrdSysError; struct sockaddr; class XrdNetIF { public: //------------------------------------------------------------------------------ //! Display the final interface configuration. //! //! @param pfx The desired message prefix (default is as shown). //------------------------------------------------------------------------------ void Display(const char *pfx="=====> "); //------------------------------------------------------------------------------ //! The enum that is used to index into ifData to get appropriate interface. //------------------------------------------------------------------------------ enum ifType {PublicV4 = 0, // PrivateVx ifNum = 4, //= ifAny) ifT = static_cast(ifAvail); name = ifName[ifT]->iVal; return ifName[ifT]->iLen; } //------------------------------------------------------------------------------ //! Copy the interface name and return port number. //! //! @param nbuff Reference to buffer where the name will be placed. It must //! be atleast 256 bytes in length. //! @param nport Place where the port number will be placed. //! @param ifT Desired ifType (PublicV6 is the default) //! //! @return The length of the name copied into the buffer. //! A value of zero indicates that no such interface exists. //------------------------------------------------------------------------------ inline int GetName(char *nbuff, int &nport, ifType ifT=PublicV6) {if (ifT >= ifAny) ifT = static_cast(ifAvail); strcpy(nbuff, ifName[ifT]->iVal); nport = ifPort; return ifName[ifT]->iLen; } //------------------------------------------------------------------------------ //! Obtain an easily digestable list of IP routable interfaces to this machine. //! //! @param ifList Place where the list of interfaces will be placed. If //! ifList is null, returns configured interface types. //! @param eText When not nil, is where to place error message text. //! //! @return Success: ifList != 0: returns the count of interfaces in the list. //! *ifList->sval[0] strlen(ifList->text) //! *ifList->sval[1] when != 0 the address is private. //! *ifList->text the interface address is standard format. //! The list of objects belongs to the caller and must be //! deleted when no longer needed. //! //! ifList == 0: returns types of configured non-local i/f. //! This is or'd values of the static const ints haveXXXX. //! //! Failure: Zero is returned. If eText is supplied, the error message, //! in persistent storage, is returned. //------------------------------------------------------------------------------ static const int haveNoGI = 0; //!< ifList == 0 && getifaddrs() is not supported static const int haveIPv4 = 1; //!< ifList == 0 && non-local ipv4 i/f found (or'd) static const int haveIPv6 = 2; //!< ifList == 0 && non-local ipv6 i/f found (or'd) static const int havePrv4 = 4; //!< ifList == 0 && private ipv4 i/f found (or'd) static const int havePrv6 = 8; //!< ifList == 0 && private ipv6 i/f found (or'd) static const int havePub4 =16; //!< ifList == 0 && public ipv4 i/f found (or'd) static const int havePub6 =32; //!< ifList == 0 && public ipv6 i/f found (or'd) static int GetIF(XrdOucTList **ifList, const char **eText=0); //------------------------------------------------------------------------------ //! Obtain an easily transmittable IP routable interfaces to this machine. //! //! @param buff Pointer to buffer to hold result which can be fed to SetIF. //! @param blen The length of the buffer (4K is really sufficient). //! @param eText When not nil, is where to place error message text. //! @param show When true configured interfaces are also displayed. //! //! @return Success: Number of bytes placed in buff, excluding the null. //! Failure: Zero is returned. If eText is supplied, the error message, //! in persistent storage, is returned. //------------------------------------------------------------------------------ static int GetIF(char *buff, int blen, const char **eText=0, bool show=false); //------------------------------------------------------------------------------ //! Obtain an easily transmittable IP routable interfaces to this machine. //! //! @param ifline Reference to a char * pointer that will get the result. //! @param eText When not nil, is where to place error message text. //! @param show When true configured interfaces are also displayed. //! //! @return Success: Number of bytes in the returned string ecluding the null. //! The caller is responsible for unallocating it via free(). //! Failure: Zero is returned. If eText is supplied, the error message, //! in persistent storage, is returned. *ifline is set to 0. //------------------------------------------------------------------------------ static int GetIF(char *&ifline, const char **eText=0, bool show=false); //------------------------------------------------------------------------------ //! Get the ifType for client connection. //! //! @param conIPv4 True if connected via IPv4, false means IPv6. //! @param hasIP64 True if the client has an IPv4 and IPv6 address. //! @param pvtIP True if the ip address is private. //! //! @return The ifType correspodning to the passed arguments. //------------------------------------------------------------------------------ static ifType GetIFType(bool conIPv4, bool hasIP64, bool pvtIP) {ifType ifT; if (conIPv4) ifT = (hasIP64 ? Public46 : PublicV4); else ifT = (hasIP64 ? Public64 : PublicV6); if (pvtIP) Privatize(ifT); return ifT; } //------------------------------------------------------------------------------ //! Determine whether or not an interface exists. //! //! @param ifT -> Desired ifType (PublicV6 is the default) //! //! @return true -> desired dest exists. //! false -> desired dest does not exist. //------------------------------------------------------------------------------ inline bool HasDest(ifType ifT=PublicV6) {return ifT >= ifAny || ifDest[ifT]->iLen != 0;} //------------------------------------------------------------------------------ //! Determine if an endpoint is this domain based on hostname. //! //! @param epaddr Pointer to the endpoint NetAddrInfo object. //! //! @result true The endpoint is in this domain. //! @result false Either the endpoint is not in this domain, is a private //! address, or is not registered in DNS. //------------------------------------------------------------------------------ static bool InDomain(XrdNetAddrInfo *epaddr); //------------------------------------------------------------------------------ //! Get the ifType selection mask for this object. //! //! @return A single char that represents the selection mask. //------------------------------------------------------------------------------ char Mask() {return ifMask;} //------------------------------------------------------------------------------ //! Convert an ifType to its corresponding selection mask. //! //! @param ifT The ifType to convert. //! //! @return A single char that represents the selection mask. //------------------------------------------------------------------------------ static char Mask(ifType ifT) {if (ifT >= ifAny) return 0x0f; return ifMaskVec[ifT]; } //------------------------------------------------------------------------------ //! Get the human readable for for an ifType. //! //! @param ifT The ifType to convert. //! //! @return A pointer to the human readable name. The string resides in static //! storage and is always valid. //------------------------------------------------------------------------------ static const char *Name(ifType ifT) {if (ifT >= ifAny) return "any"; return ifTName[ifT]; } //------------------------------------------------------------------------------ //! Get the assigned port number //! //! @return The port number. //------------------------------------------------------------------------------ inline int Port() {return ifPort;} //------------------------------------------------------------------------------ //! Make an iofType refer to the private network. //! //! @param x The iftype variable that will have the private bit set. //------------------------------------------------------------------------------ static void Privatize(ifType &x) {x = ifType(x | PrivateIF);} //------------------------------------------------------------------------------ //! Set the assigned port number. This method is not thread safe! //! //! @param pnum The port number. //! //! @return The previous port number. //------------------------------------------------------------------------------ int Port(int pnum); //------------------------------------------------------------------------------ //! Set the default assigned port number. //! //! @param pnum The port number. //------------------------------------------------------------------------------ static void PortDefault(int pnum=1094); //------------------------------------------------------------------------------ //! Routing() and SetIF() parameter. //! //! netDefault - netSplit for Routing() and Routing() value for SetIF(). //! netSplit - public and private addresses are routed separately so that //! substitution of one type of address for another is not allowed. //! netCommon - clients with private addresses also have public addresses. //! Source and target addresses should match but a public address //! may be used in the absence of a private address. //! netLocal - private addresses are registered and can be used by public //! clients within this domain. Clients with public addresses can //! be routed to private addresses. //------------------------------------------------------------------------------ enum netType {netDefault = 0, netSplit, netCommon, netLocal}; //------------------------------------------------------------------------------ //! Set default interface network routing. //! //! @param nettype Network routing (see netType definition). //------------------------------------------------------------------------------ static void Routing(netType nettype); //------------------------------------------------------------------------------ //! Set the ifData structure based on the interface string generated by GetIF(). //! //! @param src The network information of host supplying the if string. //! @param ifList The interface string, it must be null terminated. //! @param port The port associated with the interfaces; as follows: //! <0 -> Use previous setting if any. //! =0 -> use default port (the default). //! >0 -> Use the number passed. //! @param nettype Determines how undefined interfaces are resolved. See //! the netType definition. //! @param xName the known registered host name should ip address //! translation fail. //! //! @return Success: True. //! Failure: False and if eText is supplied, the error message, //! in persistent storage, is returned. //------------------------------------------------------------------------------ bool SetIF(XrdNetAddrInfo *src, const char *ifList, int port=0, netType nettype=netDefault, const char *xName=0); //------------------------------------------------------------------------------ //! Set the public and private network interface names. //! //! @param ifnames Pointer to the comma seperated interface names. This //! string is modified. //! //! @return true Names have been set. //! @return false Invalid interface name list. //------------------------------------------------------------------------------ static bool SetIFNames(char *ifnames); //------------------------------------------------------------------------------ //! Specify where messages are to be sent. //! //! @param erp Pointer to the error message object. By default, no error //! messages are printed. This is not a thread-safe call and //! the err disposition must be set at initialization time. //------------------------------------------------------------------------------ static void SetMsgs(XrdSysError *erp); //------------------------------------------------------------------------------ //! Specify wheter or not private IP addresses should be resolved. //! //! @param rval When true, private IP addresses are resolved. Otherwise, //! the IP addresses is used as the hostname. //------------------------------------------------------------------------------ static void SetRPIPA(bool rval); //------------------------------------------------------------------------------ //! Constructor and Destructor //------------------------------------------------------------------------------ XrdNetIF() : ifBuff(0), ifMask(0), ifAvail(0) {} ~XrdNetIF() {if (ifBuff) free(ifBuff);} private: struct ifAddrs {short hALen; short hDLen; bool ipV6; bool prvt; char hAddr[64]; // address char hDest[64]; // address possibly in deprecated format }; bool GenAddrs(ifAddrs &ifTab, XrdNetAddrInfo *src); bool GenAddrs(ifAddrs &ifTab, const char *hName, bool wantV6); bool GenIF(XrdNetAddrInfo **src, int srcnum, const char *xName=0); static const char *GetDomain(); static bool IsOkName(const char *ifn, short &ifIdx); void SetIFPP(); bool SetIF64(bool retVal); static bool V4LinkLocal(struct sockaddr *saP); struct ifData { short iLen; char iVal[6]; // Actually of size iLen ifData() : iLen(0) {*iVal = 0;} ~ifData() {} }; ifData *ifName[ifMax]; ifData *ifDest[ifMax]; bool ifxDNS[ifMax]; char *ifBuff; struct pInfo {char len; char val[7]; // Contains ":12345\0" pInfo() : len(0) {*val = 0;} } portSfx; int ifPort; short ifRoute; char ifMask; char ifAvail; static XrdSysError *eDest; static const char *myDomain; static char *ifCfg[2]; static const char *ifTName[ifMax]; static const char *ifMaskVec; static netType netRoutes; static int dfPort; static ifData ifNull; static bool rPIPA; }; #endif