XRootD
XrdNetIdentity.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d N e t I d e n t i t y . h h */
4 /* */
5 /* (c) 2021 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* Produced by Andrew Hanushevsky for Stanford University under contract */
7 /* DE-AC02-76-SFO0515 with the Department of Energy */
8 /* */
9 /* This file is part of the XRootD software suite. */
10 /* */
11 /* XRootD is free software: you can redistribute it and/or modify it under */
12 /* the terms of the GNU Lesser General Public License as published by the */
13 /* Free Software Foundation, either version 3 of the License, or (at your */
14 /* option) any later version. */
15 /* */
16 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19 /* License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24 /* */
25 /* The copyright holder's institutional names and contributor's names may not */
26 /* be used to endorse or promote products derived from this software without */
27 /* specific prior written permission of the institution or contributor. */
28 /******************************************************************************/
29 
30 #include <string.h>
31 #include <unistd.h>
32 
33 #include "XrdNet/XrdNetAddr.hh"
34 #include "XrdNet/XrdNetIdentity.hh"
35 #include "XrdNet/XrdNetIF.hh"
36 #include "XrdOuc/XrdOucTList.hh"
37 #include "XrdOuc/XrdOucUtils.hh"
38 #include "XrdSys/XrdSysE2T.hh"
39 
40 /******************************************************************************/
41 /* O n e T i m e S t a t i c I n i t i a l i z a t i o n */
42 /******************************************************************************/
43 
44 namespace
45 {
46 char *getMyFQN(const char *&myDom, bool &myFQN, const char *&myErr)
47 {
48  XrdNetAddr theAddr;
49  XrdOucTList *ifList, *ifNow;
50  const char *dnsName, *domP;
51  char *theName[2] = {0}, *theDom[2] = {0}, *theIPA[2] = {0}, hName[1025];
52  int hnLen;
53 
54 // Make sure domain is set to something that is valid
55 //
56  myDom = "";
57 
58 // The identity can be specified via an envar. In this case, it short circuits
59 // all the subsequent code.
60 //
61  if ((dnsName = getenv("XRDNET_IDENTITY")))
62  {if (XrdNetAddrInfo::isHostName(dnsName)
63  && !(myDom = index(dnsName, '.'))) myDom = "";
64  myFQN = false;
65  char* tmp = strdup(dnsName);
67  return tmp;
68  }
69  myFQN = true;
70 
71 // Obtain the host name, this is mandatory.
72 //
73  if (gethostname(hName, sizeof(hName)))
74  {myErr = XrdSysE2T(errno); myDom = 0; return 0;}
75  hnLen = strlen(hName);
76  XrdOucUtils::toLower(hName);
77 
78 // First step it to get all IP addresses configured on this machine
79 //
80  if (!XrdNetIF::GetIF(&ifList, &myErr))
81  {myDom = ""; return strdup(hName);}
82 
83 // Run through the interfaces and try to get the hostname associated with
84 // this machine. Note that we may have public and private addresses and
85 // they may have different hostname attached. We only accept the hostname
86 // that matches what is returned by gethostname().
87 //
88  while((ifNow = ifList))
89  {int i = (ifNow->sval[1] ? 1 : 0); // Private | public
90 
91  if (i >= 0 && theName[i] == 0 && !theAddr.Set(ifNow->text, 0)
92  && (dnsName = theAddr.Name(0,&myErr)) && (domP = index(dnsName,'.')))
93  {int n = domP - dnsName;
94  if (n == hnLen && !strncmp(hName, dnsName, n))
95  {theName[i] = strdup(dnsName);
96  theDom[i] = theName[i] + n;
97  } else {
98  if (theIPA[i]) free(theIPA[i]);
99  theIPA[i] = strdup(ifNow->text);
100  }
101  }
102  ifList = ifList->next;
103  delete ifNow;
104  }
105 
106 // Fix up error pointer
107 //
108  if (myErr == 0) myErr = "no error";
109 
110 // We prefer the public name should we have it
111 //
112  if (theName[0])
113  {if (theName[1]) free(theName[1]);
114  myDom = theDom[0];
115  return theName[0];
116  }
117 
118 // Use the private name should we have it
119 //
120  if (theName[1])
121  {myDom = theDom[1];
122  return theName[1];
123  }
124 
125 // Concote a name using old-style DNS resolution. This may not work if DNS
126 // namespaces are being used (e.g. k8s environments) or if the hostname is not
127 // resolvable. We will catch that here and move on.
128 //
129  if ((myErr = theAddr.Set(hName,0))) dnsName = 0;
130  else dnsName = theAddr.Name(0, &myErr);
131 
132 // Check if this worked
133 //
134  if (dnsName)
135  {theName[0] = strdup(dnsName);
136  if (!(myDom = index(theName[0], '.'))) myDom = "";
137  return theName[0];
138  }
139 
140 // Prefrentially return the hostname as an address as the value of gethostname()
141 // may actually fail. So, we defer naming the machine until later but we do
142 // know its IP address and that can be used as an identity. Return the public
143 // address first. Note that we prefrentially return the IPv6 address here.
144 //
145  if (theIPA[0])
146  {if (theIPA[1]) free(theIPA[1]);
147  return theIPA[0];
148  }
149  if (theIPA[1]) return theIPA[1];
150 
151 // Fallback to using the simple unqualified hostname, this still may be OK but
152 // this is likely to fail in certain situations where DNS is screwed up.
153 //
154  theName[0] = strdup(hName);
155  myDom = theName[0] + hnLen;
156  return theName[0];
157 }
158 }
159 
160 /******************************************************************************/
161 /* S t a t i c M e m b e r s */
162 /******************************************************************************/
163 
164 // Note that we are gauranteed that this will be fully initialzed prior
165 // to any method called that uses these values irrespective of static
166 // initialization order, even though statically initialized.
167 
168 const char *XrdNetIdentity::DNS_Domain;
169 const char *XrdNetIdentity::DNS_Error;
170  char *XrdNetIdentity::DNS_FQN = getMyFQN(DNS_Domain, FQN_DNS, DNS_Error);
171  bool XrdNetIdentity::FQN_DNS;
172 
173 /******************************************************************************/
174 /* D o m a i n */
175 /******************************************************************************/
176 
177 const char *XrdNetIdentity::Domain(const char **eText)
178 {
179  if (eText) *eText = DNS_Error;
180  return DNS_Domain;
181 }
182 
183 /******************************************************************************/
184 /* F Q N */
185 /******************************************************************************/
186 
187 const char *XrdNetIdentity::FQN(const char **eText)
188 {
189  if (eText) *eText = DNS_Error;
190  return DNS_FQN;
191 }
192 
193 /******************************************************************************/
194 /* s e t F Q N */
195 /******************************************************************************/
196 
197 void XrdNetIdentity::SetFQN(const char *fqn)
198 {
199  if (DNS_FQN) free(DNS_FQN);
200  DNS_FQN = strdup(fqn);
201  if (!(DNS_Domain = index(DNS_FQN, '.'))) DNS_Domain = "";
202  FQN_DNS = false;
203 }
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104
static bool isHostName(const char *name)
const char * Name(const char *eName=0, const char **eText=0)
const char * Set(const char *hSpec, int pNum=PortInSpec)
Definition: XrdNetAddr.cc:216
static int GetIF(XrdOucTList **ifList, const char **eText=0)
Definition: XrdNetIF.cc:429
static void SetFQN(const char *fqn)
static const char * Domain(const char **eText=0)
static const char * FQN(const char **etext=0)
XrdOucTList * next
Definition: XrdOucTList.hh:45
char * text
Definition: XrdOucTList.hh:46
static void toLower(char *str)