XRootD
Loading...
Searching...
No Matches
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"
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// These values are set on first use by initIdentity(), so that callers in the
45// static initializers of other files do not depend on initialization order.
46
47static char DNS_FQN[256]; // Fully qualified hostname
48static const char *DNS_Domain; // Starts with leading dot, points into DNS_FQN!
49static const char *DNS_Error; // Error indicator for debugging only
50
51static bool getMyFQN()
52{
53// Initialize name, domain, and error to empty strings
54//
55 memset(DNS_FQN, '\0', sizeof(DNS_FQN));
57 DNS_Error = nullptr;
58
59// The identity can be specified via an envar. In this case, it short circuits
60// all the subsequent code.
61//
62 const char *dnsName = nullptr;
63 if ((dnsName = getenv("XRDNET_IDENTITY")))
64 {strlcpy(DNS_FQN, dnsName, sizeof(DNS_FQN));
67 DNS_Domain = "";
68 return false;
69 }
70
71// Obtain the host name, this is mandatory.
72//
73 if (gethostname(DNS_FQN, sizeof(DNS_FQN)))
74 {DNS_Error = XrdSysE2T(errno); DNS_Domain = ""; return false;}
75
76 int hnLen = strlen(DNS_FQN);
78
79// First step it to get all IP addresses configured on this machine
80//
81 XrdOucTList *ifList = nullptr;
82 if (!XrdNetIF::GetIF(&ifList, &DNS_Error))
83 {DNS_Domain = ""; return true;}
84
85// Run through the interfaces and try to get the hostname associated with
86// this machine. Note that we may have public and private addresses and
87// they may have different hostname attached. We only accept the hostname
88// that matches what is returned by gethostname().
89//
90 XrdNetAddr theAddr;
91 const char *domP = nullptr;
92 char *theIPA[2] = { nullptr, nullptr };
93 char *theName[2] = { nullptr, nullptr };
94 XrdOucTList *ifNow = nullptr;
95
96 while((ifNow = ifList))
97 {int i = (ifNow->sval[1] ? 1 : 0); // Private | public
98
99 if (i >= 0 && theName[i] == 0 && !theAddr.Set(ifNow->text, 0)
100 && (dnsName = theAddr.Name(0,&DNS_Error)) && (domP = index(dnsName,'.')))
101 {int n = domP - dnsName;
102 if (n == hnLen && !strncmp(DNS_FQN, dnsName, n))
103 {theName[i] = strdup(dnsName);
104 } else {
105 if (theIPA[i]) free(theIPA[i]);
106 theIPA[i] = strdup(ifNow->text);
107 }
108 }
109 ifList = ifList->next;
110 delete ifNow;
111 }
112
113// Fix up error pointer
114//
115 if (DNS_Error == 0) DNS_Error = "no error";
116
117// We prefer the public name should we have it
118//
119 if (theName[0])
120 {strlcpy(DNS_FQN, theName[0], sizeof(DNS_FQN));
121 goto done;
122 }
123
124// Use the private name should we have it
125//
126 if (theName[1])
127 {strlcpy(DNS_FQN, theName[1], sizeof(DNS_FQN));
128 goto done;
129 }
130
131// Concote a name using old-style DNS resolution. This may not work if DNS
132// namespaces are being used (e.g. k8s environments) or if the hostname is not
133// resolvable. We will catch that here and move on.
134//
135 if ((DNS_Error = theAddr.Set(DNS_FQN,0))) dnsName = nullptr;
136 else dnsName = theAddr.Name(0, &DNS_Error);
137
138// Check if this worked
139//
140 if (dnsName)
141 {strlcpy(DNS_FQN, dnsName, sizeof(DNS_FQN));
142 goto done;
143 }
144
145// Prefrentially return the hostname as an address as the value of gethostname()
146// may actually fail. So, we defer naming the machine until later but we do
147// know its IP address and that can be used as an identity. Return the public
148// address first. Note that we prefrentially return the IPv6 address here.
149//
150 if (theIPA[0])
151 {strlcpy(DNS_FQN, theIPA[0], sizeof(DNS_FQN));
152 goto done;
153 }
154
155 if (theIPA[1])
156 {strlcpy(DNS_FQN, theIPA[1], sizeof(DNS_FQN));
157 goto done;
158 }
159
160// Fallback to using the simple unqualified hostname, this still may be OK but
161// this is likely to fail in certain situations where DNS is screwed up.
162//
163 DNS_Domain = "";
164 return true;
165
166done:
167 free(theName[0]);
168 free(theName[1]);
169 free(theIPA[0]);
170 free(theIPA[1]);
171
172 if (!(DNS_Domain = index(DNS_FQN, '.')))
173 DNS_Domain = "";
174 return true;
175}
176
177// Run getMyFQN() once, on first use. This requires getifaddrs(): without it,
178// XrdNetIF::GetIF() makes an XrdNetAddr for this host, which calls FQN().
179// The inline keyword lets GCC put the guard check in the callers.
180static inline void initIdentity()
181{
182 static const bool done = getMyFQN();
183 (void)done;
184}
185
186/******************************************************************************/
187/* D o m a i n */
188/******************************************************************************/
189
190const char *XrdNetIdentity::Domain(const char **eText)
191{
192 initIdentity();
193 if (eText) *eText = DNS_Error;
194 return DNS_Domain;
195}
196
197/******************************************************************************/
198/* F Q N */
199/******************************************************************************/
200
201const char *XrdNetIdentity::FQN(const char **eText)
202{
203 initIdentity();
204 if (eText) *eText = DNS_Error;
205 return DNS_FQN;
206}
207
208/******************************************************************************/
209/* s e t F Q N */
210/******************************************************************************/
211
212void XrdNetIdentity::SetFQN(const char *fqn)
213{
214 initIdentity();
215 strlcpy(DNS_FQN, fqn, sizeof(DNS_FQN));
217 if (!(DNS_Domain = index(DNS_FQN, '.'))) DNS_Domain = "";
218}
static const char * DNS_Error
static bool getMyFQN()
static void initIdentity()
static const char * DNS_Domain
static char DNS_FQN[256]
const char * XrdSysE2T(int errcode)
Definition XrdSysE2T.cc:101
size_t strlcpy(char *dst, const char *src, size_t sz)
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)
static int GetIF(XrdOucTList **ifList, const char **eText=0)
Definition XrdNetIF.cc:413
static void SetFQN(const char *fqn)
static const char * Domain(const char **eText=0)
static const char * FQN(const char **etext=0)
XrdOucTList * next
static void toLower(char *str)