XRootD
Loading...
Searching...
No Matches
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"
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
48namespace
49{
50XrdOucTList *GetLocalSite()
51 {const char *sname = getenv("XRDSITE");
52 if (!sname || !(*sname)) sname = "local";
53 return new XrdOucTList(sname);
54 }
55
56XrdOucTList *siteList = 0;
57int siteIndex = 0;
58}
59
60/******************************************************************************/
61/* Private: D i s p l a y */
62/******************************************************************************/
63
64void 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,
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
286XrdOucTList *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
310const 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}
void Display()
Definition XrdCks.cc:56
static XrdSysError eDest(0,"crypto_")
static const char * SiteName(int snum)
static XrdCmsPerfMon * loadPerfMon(XrdSysError *eDest, const char *libPath, XrdVersionInfo &urVer)
Load the performance monitor plugin.
static char * ParseManPort(XrdSysError *eDest, XrdOucStream &CFile, char *hSpec)
static bool ParseMan(XrdSysError *eDest, XrdOucTList **oldMans, char *hSpec, char *hPort, int *sPort=0, bool hush=false)
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)
static const char * GetAddrs(const char *hSpec, XrdNetAddr *aListP[], int &aListN, AddrOpts opts=allIPMap, int pNum=PortInSpec)
static int ServPort(const char *sName, bool isUDP=false, const char **eText=0)
static XrdOucTList * Hosts(const char *hSpec, int hPort=-1, int hWant=8, int *sPort=0, const char **eText=0)
void * Resolve(const char *symbl, int mcnt=1)
char * GetWord(int lowcase=0)
XrdOucTList * next
static int a2i(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition XrdOuca2x.cc:45
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)