XRootD
XrdCmsUtils.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d C m s U t i l s . c c */
4 /* */
5 /* (c) 2013 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* All Rights Reserved */
7 /* Produced by Andrew Hanushevsky for Stanford University under contract */
8 /* DE-AC02-76-SFO0515 with the Department of Energy */
9 /* */
10 /* This file is part of the XRootD software suite. */
11 /* */
12 /* XRootD is free software: you can redistribute it and/or modify it under */
13 /* the terms of the GNU Lesser General Public License as published by the */
14 /* Free Software Foundation, either version 3 of the License, or (at your */
15 /* option) any later version. */
16 /* */
17 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20 /* License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25 /* */
26 /* The copyright holder's institutional names and contributor's names may not */
27 /* be used to endorse or promote products derived from this software without */
28 /* specific prior written permission of the institution or contributor. */
29 /******************************************************************************/
30 
31 #include <cctype>
32 #include <cstdio>
33 #include <unistd.h>
34 
35 #include "XrdCms/XrdCmsUtils.hh"
36 #include "XrdNet/XrdNetAddr.hh"
37 #include "XrdNet/XrdNetUtils.hh"
38 #include "XrdOuc/XrdOuca2x.hh"
40 #include "XrdOuc/XrdOucStream.hh"
41 #include "XrdOuc/XrdOucTList.hh"
42 #include "XrdSys/XrdSysError.hh"
43 
44 /******************************************************************************/
45 /* L o c a l S t a t i c s */
46 /******************************************************************************/
47 
48 namespace
49 {
50 XrdOucTList *GetLocalSite()
51  {const char *sname = getenv("XRDSITE");
52  if (!sname || !(*sname)) sname = "local";
53  return new XrdOucTList(sname);
54  }
55 
56 XrdOucTList *siteList = 0;
57 int siteIndex = 0;
58 }
59 
60 /******************************************************************************/
61 /* Private: D i s p l a y */
62 /******************************************************************************/
63 
64 void XrdCmsUtils::Display(XrdSysError *eDest, const char *hSpec,
65  const char *hName, bool isBad)
66 {
67  XrdNetAddr *nP;
68  const char *eTxt, *eSfx = (isBad ? " *** Invalid ***" : 0);
69  int i, n, abLen, numIP = 0;
70  char *abP, aBuff[1024];
71 
72 // Get all of the addresses
73 //
74  eTxt = XrdNetUtils::GetAddrs(hName, &nP, numIP, XrdNetUtils::prefAuto, 0);
75 
76 // Check for errors
77 //
78  if (eTxt)
79  {eDest->Say("Config Manager ", hSpec, " -> ", hName, " ", eTxt);
80  return;
81  }
82  eDest->Say("Config Manager ", hSpec, " -> ", hName, eSfx);
83 
84 // Prepare the buffer
85 //
86  n = strlen(hSpec)+4;
87  if (n+64 > (int)sizeof(aBuff)) return;
88  memset(aBuff, int(' '), n);
89  abP = aBuff+n; abLen = sizeof(aBuff) - n;
90 
91 // Format the addresses
92 //
93  for (i = 0; i < numIP; i++)
94  {if (!nP[i].Format(abP, abLen, XrdNetAddrInfo::fmtAddr,
95  XrdNetAddrInfo::noPort)) break;
96  eDest->Say("Config Manager ", aBuff);
97  }
98 
99 // All done
100 //
101  delete [] nP;
102 }
103 
104 /******************************************************************************/
105 /* l o a d P e r f M o n */
106 /******************************************************************************/
107 
109  const char *libPath,
110  XrdVersionInfo &urVer)
111 {
112  XrdOucPinLoader perfLib(eDest, &urVer, "cms.perf", libPath);
113 
114  XrdCmsPerfMon **perfMon = (XrdCmsPerfMon**)perfLib.Resolve("XrdCmsPerfMonitor");
115 
116  return (perfMon ? *perfMon : 0);
117 }
118 
119 /******************************************************************************/
120 /* P a r s e M a n */
121 /******************************************************************************/
122 
124  char *hSpec, char *hPort, int *sPort, bool hush)
125 {
126  static const size_t maxSNLen = 63;
127  XrdOucTList *newMans, *newP, *oldP, *appList = (oldMans ? *oldMans : 0);
128  XrdOucTList *sP = siteList;
129  const char *eText;
130  char *plus, *atsn, *iName = 0;
131  int nPort, maxIP = 1, snum = 0;
132  bool isBad;
133 
134 // Generate local site name if we haven't done so yet
135 //
136  if (!siteList) siteList = GetLocalSite();
137 
138 // Handle site qualification first
139 //
140  if ((atsn = index(hPort, '@')))
141  {if (*(atsn+1) == '\0')
142  {eDest->Emsg("Config", "site name missing for", hSpec); return 0;}
143  *atsn++ = 0;
144  if (strlen(atsn) > maxSNLen)
145  {eDest->Emsg("Config", "site name too long for", hSpec); return 0;}
146  while(sP && strcmp(sP->text, atsn)) sP = sP->next;
147  if (sP) snum = sP->val;
148  else {siteIndex++;
149  siteList = new XrdOucTList(atsn, siteIndex, siteList);
150  snum = siteIndex;
151  }
152  }
153 
154 // Handle scope qualification next
155 //
156  if ((iName = index(hPort, '%')))
157  {if (*(iName+1) == '\0')
158  {eDest->Emsg("Config", "instance name missing for", hSpec); return 0;}
159  *iName++ = 0;
160  const char *xName = getenv("XRDNAME");
161  if (!xName || strcmp(xName, iName)) sPort = 0;
162  }
163 
164 // Check if this is a multi request
165 //
166  if (!(plus = index(hSpec, '+')) || *(plus+1) != 0) plus = 0;
167  else {*plus = 0; maxIP = 8;
168  if (XrdNetAddr::DynDNS())
169  {eDest->Emsg("Config", "Hostname globbing is not supported "
170  "via dynamic DNS!");
171  return false;
172  }
173  }
174 
175 // Check if the port was specified
176 //
177  if (isdigit(*hPort))
178  {if (XrdOuca2x::a2i(*eDest,"manager port",hPort,&nPort,1,65535))
179  return false;
180  } else {
181  if (!(nPort = XrdNetUtils::ServPort(hPort, "tcp")))
182  {eDest->Emsg("Config", "Unable to find tcp service",hPort,".");
183  return false;
184  }
185  }
186 
187 // Obtain the list. We can't fully resolve this now if we are using a dynamic
188 // DNS so that part will have to wait.
189 //
190  if (XrdNetAddr::DynDNS())
191  {if (sPort)
192  {XrdNetAddr myAddr(0), urAddr;
193  if (!urAddr.Set(hSpec, 0) && myAddr.Same(&urAddr)) *sPort = nPort;
194  }
195  newMans = new XrdOucTList(hSpec, nPort);
196  } else {
197  if (!(newMans = XrdNetUtils::Hosts(hSpec, nPort, maxIP, sPort, &eText)))
198  {char buff[1024];
199  snprintf(buff,sizeof(buff),"'%s'; %c%s",hSpec,tolower(*eText),eText+1);
200  eDest->Emsg("Config", "Unable to add host", buff);
201  return false;
202  }
203  }
204 
205 // If there is no pointer to a list, then the caller merely wanted sPort
206 //
207  if (!oldMans)
208  {while((newP = newMans)) {newMans = newMans->next; delete newP;}
209  return true;
210  }
211 
212 // Merge new list with old list
213 //
214  while((newP = newMans))
215  {newMans = newMans->next;
216  newP->ival[1] = snum;
217  oldP = *oldMans;
218  while(oldP)
219  {if (newP->val == oldP->val && !strcmp(newP->text, oldP->text))
220  {eDest->Say("Config warning: duplicate manager ",newP->text);
221  delete newP;
222  break;
223  }
224  oldP = oldP->next;
225  }
226  if (!oldP)
227  {if (!plus || strcmp(hSpec, newP->text)) isBad = false;
228  else {eDest->Say("Config warning: "
229  "Cyclic DNS registration for ",newP->text,"\n"
230  "Config warning: This cluster will exhibit "
231  "undefined behaviour!!!");
232  isBad = true;
233  }
234  appList = SInsert(appList, newP);
235  if (plus && !hush) Display(eDest, hSpec, newP->text, isBad);
236  }
237  }
238 
239 // Set the new list and return
240 //
241  *oldMans = appList;
242  return true;
243 }
244 
245 /******************************************************************************/
246 /* P a r s e M a n P o r t */
247 /******************************************************************************/
248 
250  char *hSpec)
251 {
252  char *pSpec;
253 
254 // Screen out IPV6 specifications
255 //
256  if (*hSpec == '[')
257  {if (!(pSpec = index(hSpec, ']')))
258  {eDest->Emsg("Config", "Invalid manager specification -",hSpec);
259  return 0;
260  }
261  } else pSpec = hSpec;
262 
263 // Grab the port number if in the host name. Otherwise make sure it follows.
264 //
265  if ((pSpec = index(pSpec, ':')))
266  {if (!(*(pSpec+1))) pSpec = 0;
267  else *pSpec++ = '\0';
268  }
269  else if (!(pSpec = CFile.GetWord()) || !strcmp(pSpec, "if")) pSpec = 0;
270 
271 // We should have a port specification now
272 //
273  if (!pSpec) {eDest->Emsg("Config", "manager port not specified for", hSpec);
274  return 0;
275  }
276 
277 // All is well
278 //
279  return strdup(pSpec);
280 }
281 
282 /******************************************************************************/
283 /* Private: S I n s e r t */
284 /******************************************************************************/
285 
286 XrdOucTList *XrdCmsUtils::SInsert(XrdOucTList *oldP, XrdOucTList *newP)
287 {
288  XrdOucTList *fstP = oldP, *preP = 0;
289 
290 // We insert in logically increasing order
291 //
292  while(oldP && (newP->val < oldP->val || strcmp(newP->text, oldP->text) < 0))
293  {preP = oldP; oldP = oldP->next;}
294 
295 // Insert the new element
296 //
297  if (preP) preP->next = newP;
298  else fstP = newP;
299  newP->next = oldP;
300 
301 // Return the first element in the list (may have changed)
302 //
303  return fstP;
304 }
305 
306 /******************************************************************************/
307 /* S i t e N a m e */
308 /******************************************************************************/
309 
310 const char *XrdCmsUtils::SiteName(int snum)
311 {
312  XrdOucTList *sP = siteList;
313 
314 // Find matching site
315 //
316  while(sP && snum != sP->val) sP = sP->next;
317 
318 // Return result
319 //
320  return (sP ? sP->text : "anonymous");
321 }
static XrdSysError eDest(0,"crypto_")
static const char * SiteName(int snum)
Definition: XrdCmsUtils.cc:310
static XrdCmsPerfMon * loadPerfMon(XrdSysError *eDest, const char *libPath, XrdVersionInfo &urVer)
Load the performance monitor plugin.
Definition: XrdCmsUtils.cc:108
static char * ParseManPort(XrdSysError *eDest, XrdOucStream &CFile, char *hSpec)
Definition: XrdCmsUtils.cc:249
static bool ParseMan(XrdSysError *eDest, XrdOucTList **oldMans, char *hSpec, char *hPort, int *sPort=0, bool hush=false)
Definition: XrdCmsUtils.cc:123
static const int noPort
Do not add port number.
@ fmtAddr
Address using suitable ipv4 or ipv6 format.
static bool DynDNS()
Definition: XrdNetAddr.hh:52
const char * Set(const char *hSpec, int pNum=PortInSpec)
Definition: XrdNetAddr.cc:216
static const char * GetAddrs(const char *hSpec, XrdNetAddr *aListP[], int &aListN, AddrOpts opts=allIPMap, int pNum=PortInSpec)
Definition: XrdNetUtils.cc:239
static int ServPort(const char *sName, bool isUDP=false, const char **eText=0)
Definition: XrdNetUtils.cc:839
static XrdOucTList * Hosts(const char *hSpec, int hPort=-1, int hWant=8, int *sPort=0, const char **eText=0)
Definition: XrdNetUtils.cc:541
void * Resolve(const char *symbl, int mcnt=1)
char * GetWord(int lowcase=0)
XrdOucTList * next
Definition: XrdOucTList.hh:45
char * text
Definition: XrdOucTList.hh:46
static int a2i(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition: XrdOuca2x.cc:45
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
Definition: XrdSysError.cc:141