Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-29 09:35:20

0001 #ifndef __XRDNETUTILS_HH__
0002 #define __XRDNETUTILS_HH__
0003 /******************************************************************************/
0004 /*                                                                            */
0005 /*                        X r d N e t U t i l s . h h                         */
0006 /*                                                                            */
0007 /* (c) 2025 by the Board of Trustees of the Leland Stanford, Jr., University  */
0008 /*                            All Rights Reserved                             */
0009 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
0010 /*              DE-AC02-76-SFO0515 with the Department of Energy              */
0011 /*                                                                            */
0012 /* This file is part of the XRootD software suite.                            */
0013 /*                                                                            */
0014 /* XRootD is free software: you can redistribute it and/or modify it under    */
0015 /* the terms of the GNU Lesser General Public License as published by the     */
0016 /* Free Software Foundation, either version 3 of the License, or (at your     */
0017 /* option) any later version.                                                 */
0018 /*                                                                            */
0019 /* XRootD is distributed in the hope that it will be useful, but WITHOUT      */
0020 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or      */
0021 /* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public       */
0022 /* License for more details.                                                  */
0023 /*                                                                            */
0024 /* You should have received a copy of the GNU Lesser General Public License   */
0025 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file  */
0026 /* COPYING (GPL license).  If not, see <http://www.gnu.org/licenses/>.        */
0027 /*                                                                            */
0028 /* The copyright holder's institutional names and contributor's names may not */
0029 /* be used to endorse or promote products derived from this software without  */
0030 /* specific prior written permission of the institution or contributor.       */
0031 /******************************************************************************/
0032 
0033 #include <string>
0034 #include <vector>
0035 #include <sstream>
0036 #include <cstdint>
0037 
0038 #include "XrdOuc/XrdOucEnum.hh"
0039 
0040 class XrdOucTList;
0041 class XrdNetAddr;
0042 union XrdNetSockAddr;
0043 
0044 namespace XrdNetSpace {struct hpSpec;}
0045   
0046 class XrdNetUtils
0047 {
0048 public:
0049 
0050 //------------------------------------------------------------------------------
0051 //! Compare two IP addresses and indicate differe\nces, if any.
0052 //!
0053 //! @param  ip1      The first address.
0054 //! @param  ip2      The second addres.
0055 //! @param  psame    If not zero set to true if ports are the same, o/w false.
0056 //!
0057 //! @return IPSame   The addresses are the same.
0058 //!         IPDFam   The addresses differ in address family.
0059 //!         IPDiff   The addresses have different destination, same family.
0060 //!         IPNSuf   The address family of one or both addresses not supported.
0061 //------------------------------------------------------------------------------
0062 
0063 enum IPComp {IPSame = 0, IPDFam, IPDiff, IPNSup};
0064 
0065 static
0066 IPComp      Compare(XrdNetSockAddr& ip1, XrdNetSockAddr& ip2, bool* psame=0);
0067 
0068 //------------------------------------------------------------------------------
0069 //! Decode an "encoded" ipv6/4 address and place it "sockaddr" type structure.
0070 //!
0071 //! @param  sadr     address of the union that will hold the results.
0072 //! @param  buff     address of buffer that holds the encoding.
0073 //! @param  blen     length of the string (it need not be null terminated).
0074 //!
0075 //! @return > 0      the port number in host byte order.
0076 //!         = 0      the port number was not set.
0077 //!         < 0      the encoding was not correct.
0078 //------------------------------------------------------------------------------
0079 
0080 static int  Decode(XrdNetSockAddr *sadr, const char *buff, int blen);
0081 
0082 //------------------------------------------------------------------------------
0083 //! Encode the address and return it in a supplied buffer.
0084 //!
0085 //! @param  sadr     address of the union that holds the IPV4/6 address.
0086 //! @param  buff     address of buffer to hold the null terminated encoding.
0087 //! @param  blen     length of the buffer. It6 should be at least 40 bytes.
0088 //! @param  port     optional port value to use as opposed to the one present
0089 //!                  in sockaddr sadr. The port must be in host order.
0090 //!
0091 //! @return > 0      the length of the encoding less the null byte.
0092 //!         = 0      current address format not supported for encoding.
0093 //!         < 0      buffer is too small; abs(retval) bytes needed.
0094 //------------------------------------------------------------------------------
0095 
0096 static int  Encode(const XrdNetSockAddr *sadr, char *buff, int blen, int port=-1);
0097 
0098 
0099 //------------------------------------------------------------------------------
0100 //! Version 1: Return multiple addresses associated with a host or IP address.
0101 //!
0102 //! @param  hSpec    -> convert specification to addresses. Valid formats:
0103 //!                     IP.v4:   nnn.nnn.nnn.nnn[:<port>]
0104 //!                     IP.v6:   [ipv6_addr][:<port>]
0105 //!                     IP.xx:   name[:port] xx is determined by getaddrinfo()
0106 //! @param  aListP   place where the pointer to the returned array of XrdNetAddr
0107 //!                  objects is to be placed. Set to zero if none returned. The
0108 //!                  caller must delete this array when no longer needed.
0109 //! @param  aListN   place where the number of elements in aListP are to be
0110 //!                  returned.
0111 //! @param  opts     Options on what to return. Choose one of:
0112 //!                  allIPMap - all  IPv6 and   mapped IPv4 addrs (default)
0113 //!                  allIPv64 - all  IPv6 and unmapped IPv4 addrs
0114 //!                  allV4Map - all    mapped IPV4 addrs.
0115 //!                  onlyIPv6 - only          IPv6 addrs
0116 //!                  onlyIPv4 - only unmapped IPv4 addrs
0117 //!                  prefIPv6 - only IPv6 addrs; if none, mapped IPv4 addrs
0118 //!                  prefAuto - Returns addresses based on configured non-local
0119 //!                             interfaces. The returned addresses will be
0120 //!                             normally useable on this host and may be IPv4,
0121 //!                             IPv6, mapped IPv4, or a mixture.
0122 //!                  The above may be or'd with one or more of the following:
0123 //!                  onlyUDP  - only addrs valid for UDP connections else TCP
0124 //!                  order46  - List IPv4 addresses (mapped or native) first.
0125 //!                  order64  - List IPv6 addresses first.
0126 //! @param  pNum     >= 0 uses the value as the port number regardless of what
0127 //!                       is in hSpec, should it be supplied. However, if is
0128 //!                       present, it must be a valid port number.
0129 //!                  <  0 uses the positive value as the port number if the
0130 //!                       port number has not been specified in hSpec.
0131 //!                  **** When set to PortInSpec(the default, see below) the
0132 //!                       port number/name must be specified in hSpec. If it is
0133 //!                       not, an error is returned.
0134 //!                  **** When set to NoPortRaw then hSpec does not contain a
0135 //!                       port number and is a host name, IPv4 address, or an
0136 //!                       IPv6 address *without* surrounding brackets.
0137 //!
0138 //! @return Success: 0 with aListN set to the number of elements in aListP.
0139 //!         Failure: the error message text describing the error and aListP
0140 //!                  and aListN is set to zero.
0141 //------------------------------------------------------------------------------
0142 
0143 enum AddrOpts {allIPMap=  0, allIPv64=  1, allV4Map=  2,
0144                onlyIPv6=  3, onlyIPv4=  4, prefIPv6=  8,
0145                prefAuto= 16, order46 = 32, order64 = 64,
0146                onlyUDP =128
0147               };
0148 
0149 static const int PortInSpec = (int)0x80000000;
0150 static const int NoPortRaw  = (int)0xC0000000;
0151 
0152 static
0153 const char  *GetAddrs(const char *hSpec, XrdNetAddr *aListP[], int &aListN,
0154                       AddrOpts    opts=allIPMap, int pNum=PortInSpec);
0155 
0156 //------------------------------------------------------------------------------
0157 //! Version 2: Return multiple addresses associated with a host or IP address.
0158 //!
0159 //! @param  hSpec    Reference to address specification (see version 1).
0160 //! @param  aVec     Reference to the vector to contain addresses.
0161 //! @param  ordn     Pointer to where the partition ordinal is to be stored.
0162 //! @param  opts     Options on what to return (see version 1).
0163 //! @param  pNum     Port number argument (see version 1).
0164 //!
0165 //! @return Success: 0 is returned. When ordn is not nil, the number of IPv4
0166 //!                  entries (for order46) or IPv6 (for order64) entries that
0167 //!                  appear in the front of the vector. If ordering is not
0168 //!                  specified, the value is set to the size of the vector.
0169 //!         Failure: the error message text describing the error and aVec is
0170 //!                  cleared (i.e. has no elements).
0171 //------------------------------------------------------------------------------
0172 
0173 static
0174 const char  *GetAddrs(const std::string &hSpec, std::vector<XrdNetAddr> &aVec,
0175                       int *ordn=0, AddrOpts opts=allIPMap, int pNum=PortInSpec);
0176 
0177 //------------------------------------------------------------------------------
0178 //! Version 3: Return multiple addresses associated with a list of host or
0179 //! IP addresses.
0180 //!
0181 //! @param  hSVec    vector of address specification (see version 1). Note that
0182 //!                  this version requires hSVec entries to have a port number.
0183 //! @param  aVec     Reference to the vector to contain addresses.
0184 //! @param  ordn     Pointer to where the partition ordinal is to be stored.
0185 //! @param  opts     Options on what to return (see version 1).
0186 //! @param  rotNum   The rotation factor to order addresses in the result.
0187 //! @param  force    When true resolution errors are ignored.
0188 //!
0189 //! @return Success: 0 is returned. When ordn is not nil, the number of IPv4
0190 //!                  entries (for order46) or IPv6 (for order64) entries that
0191 //!                  appear in the front of the vector. If ordering is not
0192 //!                  specified, the value is set to the size of the vector.
0193 //!         Failure: the error message text describing the error and aVec is
0194 //!                  cleared (i.e. has no elements).
0195 //------------------------------------------------------------------------------
0196 
0197 static
0198 const char  *GetAddrs(std::vector<std::string> &hSVec,
0199                       std::vector<XrdNetAddr>  &aVec,
0200                       int *ordn=0, AddrOpts opts=allIPMap,
0201                       unsigned int rotNum=0, bool force=false);
0202 
0203 //------------------------------------------------------------------------------
0204 //! Obtain connection information from a socket.
0205 //!
0206 //! @param  fd       The file descriptor of the socket whose address is to be
0207 //!                  converted. The sign of the fd indicates which address:
0208 //!                  fd > 0 the peer  address is used (i.e. getpeername)
0209 //!                  fd < 0 the local address is used (i.e. getsockname)
0210 //! @param  theAddr  pointer to a buffer of theAlen bytes where the text
0211 //!                  version of the IP address is to be returned. The text
0212 //!                  uses the actual native address format. If theAddr is
0213 //!                  nil or theAlen is not positive, only the port and
0214 //!                  address type are returned.
0215 //! @param  theALen  length of the theAddr buffer.
0216 //! @param  theType  either the character 4 (IPv4) or 6 (IPv6) is returned.
0217 //!                  corrresponding to the address family. Note that should
0218 //!                  be AF_INET6 but the address is mapped, '4' is returned.
0219 //!
0220 //! @return Success: >= 0 corresponding to the port number.
0221 //! @return Failure: <  0 corresponding to -errno.
0222 //------------------------------------------------------------------------------
0223 
0224 static
0225 int          GetSokInfo(int fd, char *theAddr, int theALen, char &theType);
0226 
0227 //------------------------------------------------------------------------------
0228 //! Obtain an easily digestable list of hosts. This is the list of up to eight
0229 //! unique aliases (i.e. with different addresses) assigned to a base hostname.
0230 //!
0231 //! @param  hSpec    the host specification suitable for XrdNetAddr.Set().
0232 //! @param  hPort    When >= 0 specified the port to use regardless of hSpec.
0233 //!                  When <  0 the port must be present in hSpec.
0234 //! @param  hWant    Maximum number of list entries wanted. If hWant is greater
0235 //!                  that eight it is set eigth.
0236 //! @param  sPort    If not nil, the *sPort will be set to hPort if and only if
0237 //!                  the IP address in one of the entries matches the host
0238 //!                  address. Otherwise, the value is unchanged.
0239 //! @param  eText    When not nil, is where to place error message text.
0240 //!
0241 //! @return Success: Pointer to a list of XrdOucTList objects where
0242 //!                  p->val  is the port number
0243 //!                  p->text is the host name.
0244 //!                  The list of objects belongs to the caller.
0245 //!         Failure: A nil pointer is returned. If eText is supplied, the error
0246 //!                  message, in persistent storage, is returned.
0247 //------------------------------------------------------------------------------
0248 
0249 static
0250 XrdOucTList *Hosts(const char  *hSpec, int hPort=-1, int hWant=8, int *sPort=0,
0251                                const char **eText=0);
0252 
0253 //------------------------------------------------------------------------------
0254 //! Convert an IP address/port (V4 or V6) into the standard V6 RFC ASCII
0255 //! representation: "[address]:port".
0256 //!
0257 //! @param  sAddr    Address to convert. This is either sockaddr_in or
0258 //!                  sockaddr_in6 cast to struct sockaddr.
0259 //! @param  bP       points to a buffer large enough to hold the result.
0260 //!                  A buffer 64 characters long will always be big enough.
0261 //! @param  bL       the actual size of the buffer.
0262 //! @param  opts     Formating options:
0263 //!                  noPort  - does not suffix the port number with ":port".
0264 //!                  oldFmt  - use the deprecated format for an IPV4 mapped
0265 //!                            address: [::d.d.d.d] vs  [::ffff:d.d.d.d].
0266 //!
0267 //! @return Success: The length of the formatted address is returned.
0268 //! @return Failure: Zero is returned and the buffer state is undefined.
0269 //!                  Failure occurs when the buffer is too small or the address family
0270 //!                  (sAddr->sa_family) is neither AF_INET nor AF_INET6.
0271 //------------------------------------------------------------------------------
0272 
0273 static const int noPort = 1;
0274 static const int oldFmt = 2;
0275 
0276 static int IPFormat(const struct sockaddr *sAddr, char *bP, int bL, int opts=0);
0277 
0278 //------------------------------------------------------------------------------
0279 //! Convert an IP socket address/port (V4 or V6) into the standard V6 RFC ASCII
0280 //! representation: "[address]:port".
0281 //!
0282 //! @param  fd       The file descriptor of the socket whose address is to be
0283 //!                  converted. The sign of the fd indicates which address:
0284 //!                  fd > 0 the peer  address is used (i.e. getpeername)
0285 //!                  fd < 0 the local address is used (i.e. getsockname)
0286 //! @param  bP       points to a buffer large enough to hold the result.
0287 //!                  A buffer 64 characters long will always be big enough.
0288 //! @param  bL       the actual size of the buffer.
0289 //! @param  opts     Formating options:
0290 //!                  noPort  - does not suffix the port number with ":port".
0291 //!                  oldFmt  - use the deprecated format for an IPV4 mapped
0292 //!                            address: [::d.d.d.d] vs  [::ffff:d.d.d.d].
0293 //!
0294 //! @return Success: The length of the formatted address is returned.
0295 //! @return Failure: Zero is returned and the buffer state is undefined.
0296 //!                  Failure occurs when the buffer is too small or the file
0297 //!                  descriptor does not refer to an open socket.
0298 //------------------------------------------------------------------------------
0299 
0300 static int IPFormat(int fd, char *bP, int bL, int opts=0);
0301 
0302 //------------------------------------------------------------------------------
0303 //! Determine if a hostname matches a pattern.
0304 //!
0305 //! @param  hName    the name of the host.
0306 //! @param  pattern  the pattern to match against. The pattern may contain one
0307 //!                  If the pattern contains a single asterisk, then the prefix
0308 //!                  of hName is compared with the characters before the '*' and
0309 //!                  the suffix of hName is compared with the character after.
0310 //!                  If the pattern ends with a plus, the all then pattern is
0311 //!                  taken as a hostname (less '+') and expanded to all possible
0312 //!                  hostnames and each one is compared with hName. If the
0313 //!                  pattern contains both, the asterisk rule is used first.
0314 //!                  If it contains neither then strict equality is used.
0315 //!
0316 //! @return Success: True,  the pattern matches.
0317 //!         Failure: False, no match found.
0318 //------------------------------------------------------------------------------
0319 
0320 static bool Match(const char *hName, const char *pattern);
0321 
0322 //------------------------------------------------------------------------------
0323 //! Get the fully qualified name of the current host.
0324 //!
0325 //! @param  eName    The name to be returned when the host name or its true
0326 //!                  address could not be returned. The pointer may be nil.
0327 //! @param  eText    When supplied will hold 0 if no errors occurred or error
0328 //!                  message text, in persistent storage, describing why the
0329 //!                  error-triggered alternate name was returned.
0330 //!                  If it contains neither then strict equality is used.
0331 //!
0332 //! @return An strdup() copy of the host name, address , or eName; unless eName
0333 //!         is nil, in which case a nil pointer is returned. The caller is
0334 //!         responsible for freeing any returned string using free().
0335 //------------------------------------------------------------------------------
0336 
0337 static char *MyHostName(const char *eName="*unknown*", const char **eText=0);
0338 
0339 //------------------------------------------------------------------------------
0340 //! Get the supported network protocols.
0341 //!
0342 //! @param  netqry   An NetType enum specifying the protocol to inspect.
0343 //! @param  eText    When not nil, is where to place error message text.
0344 //!
0345 //! @return One the the NetProt enums (see below). When hasNone is returned
0346 //!         and eText is not nill it will point to a static string that gives
0347 //!         the reason. If the reason is a null string, the query was successful
0348 //!         but returned no matching protocols.
0349 //------------------------------------------------------------------------------
0350 
0351 enum NetProt {hasNone  = 0, //!< Unable to determine available protocols
0352               hasIPv4  = 1, //<! Has only IPv4 capability
0353               hasIPv6  = 2, //<! Has only IPv6 capability
0354               hasIP64  = 3, //<! Has IPv4 IPv6 capability (dual stack)
0355               hasPub4  = 4, //<! Has IPv4 public address  (or'd with above)
0356               hasPub6  = 8  //<! Has IPv6 public address  (or'd with above)
0357              };
0358 
0359 enum NetType {qryINET  = 0,//!< Only consider internet protocols via DNS
0360               qryINIF  = 1 //!< Only consider internet protocols via ifconfig
0361              };
0362 
0363 static NetProt      NetConfig(NetType netquery=qryINET, const char **eText=0);
0364 
0365 //------------------------------------------------------------------------------
0366 //! Parse an IP or host name specification.
0367 //!
0368 //! @param  hSpec    the name or IP address of the host. As one of the following
0369 //!                  "[<ipv6>]:<port>", "<ipv4>:<port>", or "<name>:<port>".
0370 //! @param  hName    place where the starting address of the host is placed.
0371 //! @param  hNend    place where the ending   address+1 is placed. This will
0372 //!                  point to either ']', ':', or a null byte.
0373 //! @param  hPort    place where the starting address of the port is placed.
0374 //!                  If no ":port" was found, this will contain *hNend.
0375 //! @param  hPend    place where the ending   address+1 is placed. If no port
0376 //!                  If no ":port" was found, this will contain *hNend.
0377 //!
0378 //! @return Success: True.
0379 //!         Failure: False, hSpec is not valid. Some output parameters may have
0380 //!                  been set but shlould be ignored.
0381 //------------------------------------------------------------------------------
0382 
0383 static bool Parse(const char *hSpec, const char **hName, const char **hNend,
0384                                      const char **hPort, const char **hPend);
0385 
0386 //------------------------------------------------------------------------------
0387 //! Obtain the numeric port associated with a file descriptor.
0388 //!
0389 //! @param  fd       the file descriptor number.
0390 //! @param  eText    when not null, the reason for a failure is returned.
0391 //!
0392 //! @return Success: The positive port number.
0393 //!         Failure: 0 is returned and if eText is not null, the error message.
0394 //------------------------------------------------------------------------------
0395 
0396 static int  Port(int fd, const char **eText=0);
0397 
0398 //------------------------------------------------------------------------------
0399 //! Obtain the protocol identifier.
0400 //!
0401 //! @param  pName    the name of the protocol (e.g. "tcp").
0402 //!
0403 //! @return The protocol identifier.
0404 //------------------------------------------------------------------------------
0405 
0406 static int  ProtoID(const char *pName);
0407 
0408 //------------------------------------------------------------------------------
0409 //! Obtain the numeric port corresponding to a symbolic name.
0410 //!
0411 //! @param  sName    the name of the service or a numeric port number.
0412 //! @param  isUDP    if true, returns the UDP service port o/w the TCP service
0413 //! @param  eText    when not null, the reason for a failure is returned.
0414 //!
0415 //! @return Success: The positive port number.
0416 //!         Failure: 0 is returned and if eText is not null, the error message.
0417 //------------------------------------------------------------------------------
0418 
0419 static int  ServPort(const char *sName, bool isUDP=false, const char **eText=0);
0420 
0421 //------------------------------------------------------------------------------
0422 //! Set the family and hints to be used in GetAddrs() with prefAuto. This is
0423 //! used within this class and by XrdNetAddr when the IP mode changes.  It is
0424 //! meant for internal use only.
0425 //!
0426 //! @param  aOpts    Is one of the following from the AddrOpts enum:
0427 //!                  allIPMap - Use IPv6 and mapped IPv4 addrs (default)
0428 //!                  onlyIPv4 - Use only IPv4 addresses.
0429 //!                  prefAuto - Determine proper options based on configuration.
0430 //!
0431 //! @return The getaddrinfo() hints value that should be used.
0432 //------------------------------------------------------------------------------
0433 
0434 static int  SetAuto(AddrOpts aOpts=allIPMap);
0435 
0436 //------------------------------------------------------------------------------
0437 //! Check if whether or not a host name represents more than one unique host.
0438 //!
0439 //! @param  hSpec    the host specification suitable for XrdNetAddr.Set().
0440 //! @param  eText    When not nil, is where to place error message text.
0441 //!
0442 //! @return True is this is a simple single host. False if the name represensts
0443 //!         more than one single host.
0444 //------------------------------------------------------------------------------
0445 
0446 static bool Singleton(const char  *hSpec, const char **eText=0);
0447 
0448 static bool ConnectWithTimeout(int sockfd, const struct sockaddr* clientAddr, size_t clientAddrLen,uint32_t timeout_sec, std::stringstream & errMsg);
0449 
0450 //------------------------------------------------------------------------------
0451 //! Constructor
0452 //------------------------------------------------------------------------------
0453 
0454             XrdNetUtils() {}
0455 
0456 //------------------------------------------------------------------------------
0457 //! Destructor
0458 //------------------------------------------------------------------------------
0459 
0460            ~XrdNetUtils() {}
0461 private:
0462 
0463 static void FillAddr(XrdNetSpace::hpSpec &aBuff, XrdNetAddr *aVec,
0464                      int *ordn=0, unsigned int rotNum=0);
0465 static
0466 const char *GetAInfo(XrdNetSpace::hpSpec &aBuff);
0467 static void GetHints(XrdNetSpace::hpSpec &aBuff, AddrOpts opts);
0468 static
0469 const char *GetHostPort(XrdNetSpace::hpSpec &aBuff, const char *hSpec, int pNum);
0470 static
0471 const char *getMyFQN(const char *&myDom);
0472 static int setET(const char **errtxt, int rc);
0473 static bool SetSockBlocking(int sockfd, bool blocking, std::stringstream & errMsg);
0474 static int autoFamily;
0475 static int autoHints;
0476 };
0477 
0478 XRDOUC_ENUM_OPERATORS(XrdNetUtils::AddrOpts)
0479 
0480 #endif