#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