/******************************************************************************/ /* */ /* X r d C m s U t i l s . c c */ /* */ /* (c) 2013 by the Board of Trustees of the Leland Stanford, Jr., University */ /* All Rights Reserved */ /* Produced by Andrew Hanushevsky for Stanford University under contract */ /* DE-AC02-76-SFO0515 with the Department of Energy */ /* */ /* This file is part of the XRootD software suite. */ /* */ /* XRootD is free software: you can redistribute it and/or modify it under */ /* the terms of the GNU Lesser General Public License as published by the */ /* Free Software Foundation, either version 3 of the License, or (at your */ /* option) any later version. */ /* */ /* XRootD is distributed in the hope that it will be useful, but WITHOUT */ /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ /* License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License */ /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ /* COPYING (GPL license). If not, see . */ /* */ /* The copyright holder's institutional names and contributor's names may not */ /* be used to endorse or promote products derived from this software without */ /* specific prior written permission of the institution or contributor. */ /******************************************************************************/ #include #include #include #include "XrdCms/XrdCmsUtils.hh" #include "XrdNet/XrdNetAddr.hh" #include "XrdNet/XrdNetUtils.hh" #include "XrdOuc/XrdOuca2x.hh" #include "XrdOuc/XrdOucStream.hh" #include "XrdOuc/XrdOucTList.hh" #include "XrdSys/XrdSysError.hh" /******************************************************************************/ /* L o c a l S t a t i c s */ /******************************************************************************/ namespace { XrdOucTList *GetLocalSite() {const char *sname = getenv("XRDSITE"); if (!sname || !(*sname)) sname = "local"; return new XrdOucTList(sname); } XrdOucTList *siteList = 0; int siteIndex = 0; } /******************************************************************************/ /* Private: D i s p l a y */ /******************************************************************************/ void XrdCmsUtils::Display(XrdSysError *eDest, const char *hSpec, const char *hName, bool isBad) { XrdNetAddr *nP; const char *eTxt, *eSfx = (isBad ? " *** Invalid ***" : 0); int i, n, abLen, numIP = 0; char *abP, aBuff[1024]; // Get all of the addresses // eTxt = XrdNetUtils::GetAddrs(hName, &nP, numIP, XrdNetUtils::prefAuto, 0); // Check for errors // if (eTxt) {eDest->Say("Config Manager ", hSpec, " -> ", hName, " ", eTxt); return; } eDest->Say("Config Manager ", hSpec, " -> ", hName, eSfx); // Prepare the buffer // n = strlen(hSpec)+4; if (n+64 > (int)sizeof(aBuff)) return; memset(aBuff, int(' '), n); abP = aBuff+n; abLen = sizeof(aBuff) - n; // Format the addresses // for (i = 0; i < numIP; i++) {if (!nP[i].Format(abP, abLen, XrdNetAddrInfo::fmtAddr, XrdNetAddrInfo::noPort)) break; eDest->Say("Config Manager ", aBuff); } // All done // delete [] nP; } /******************************************************************************/ /* P a r s e M a n */ /******************************************************************************/ bool XrdCmsUtils::ParseMan(XrdSysError *eDest, XrdOucTList **oldMans, char *hSpec, char *hPort, int *sPort, bool hush) { static const size_t maxSNLen = 63; XrdOucTList *newMans, *newP, *oldP, *appList = (oldMans ? *oldMans : 0); XrdOucTList *sP = siteList; const char *eText; char *plus, *atsn; int nPort, maxIP = 1, snum = 0; bool isBad; // Generate local site name if we haven't done so yet // if (!siteList) siteList = GetLocalSite(); // Handle site qualification first // if ((atsn = index(hPort, '@'))) {if (*(atsn+1) == '\0') {eDest->Emsg("Config", "site name missing for", hSpec); return 0;} *atsn++ = 0; if (strlen(atsn) > maxSNLen) {eDest->Emsg("Config", "site name too long for", hSpec); return 0;} while(sP && strcmp(sP->text, atsn)) sP = sP->next; if (sP) snum = sP->val; else {siteIndex++; siteList = new XrdOucTList(atsn, siteIndex, siteList); snum = siteIndex; } } // Check if this is a multi request // if (!(plus = index(hSpec, '+')) || *(plus+1) != 0) plus = 0; else {*plus = 0; maxIP = 8;} // Check if the port was specified // if (isdigit(*hPort)) {if (XrdOuca2x::a2i(*eDest,"manager port",hPort,&nPort,1,65535)) return false; } else { if (!(nPort = XrdNetUtils::ServPort(hPort, "tcp"))) {eDest->Emsg("Config", "Unable to find tcp service",hPort,"."); return false; } } // Obtain the list // if (!(newMans = XrdNetUtils::Hosts(hSpec, nPort, maxIP, sPort, &eText))) {char buff[1024]; snprintf(buff, sizeof(buff), "; %s", eText); eDest->Emsg("Config", "Unable to add host", hSpec, buff); return false; } // If there is no pointer to a list, then the caller merely wanted sPort // if (!oldMans) {while((newP = newMans)) {newMans = newMans->next; delete newP;} return true; } // Merge new list with old list // while((newP = newMans)) {newMans = newMans->next; newP->ival[1] = snum; oldP = *oldMans; while(oldP) {if (newP->val == oldP->val && !strcmp(newP->text, oldP->text)) {eDest->Say("Config warning: duplicate manager ",newP->text); delete newP; break; } oldP = oldP->next; } if (!plus || strcmp(hSpec, newP->text)) isBad = false; else {eDest->Say("Config warning: " "Cyclic DNS registration for ",newP->text,"\n" "Config warning: This cluster will exhibit " "undefined behaviour!!!"); isBad = true; } if (!oldP) {appList = SInsert(appList, newP); if (plus && !hush) Display(eDest, hSpec, newP->text, isBad); } } // Set the new list and return // *oldMans = appList; return true; } /******************************************************************************/ /* P a r s e M a n P o r t */ /******************************************************************************/ char *XrdCmsUtils::ParseManPort(XrdSysError *eDest, XrdOucStream &CFile, char *hSpec) { char *pSpec; // Screen out IPV6 specifications // if (*hSpec == '[') {if (!(pSpec = index(hSpec, ']'))) {eDest->Emsg("Config", "Invalid manager specification -",hSpec); return 0; } } else pSpec = hSpec; // Grab the port number if in the host name. Otherwise make sure it follows. // if ((pSpec = index(pSpec, ':'))) {if (!(*(pSpec+1))) pSpec = 0; else *pSpec++ = '\0'; } else if (!(pSpec = CFile.GetWord()) || !strcmp(pSpec, "if")) pSpec = 0; // We should have a port specification now // if (!pSpec) {eDest->Emsg("Config", "manager port not specified for", hSpec); return 0; } // All is well // return strdup(pSpec); } /******************************************************************************/ /* Private: S I n s e r t */ /******************************************************************************/ XrdOucTList *XrdCmsUtils::SInsert(XrdOucTList *oldP, XrdOucTList *newP) { XrdOucTList *fstP = oldP, *preP = 0; // We insert in logically increasing order // while(oldP && (newP->val < oldP->val || strcmp(newP->text, oldP->text) < 0)) {preP = oldP; oldP = oldP->next;} // Insert the new element // if (preP) preP->next = newP; else fstP = newP; newP->next = oldP; // Return the first element in the list (may have changed) // return fstP; } /******************************************************************************/ /* S i t e N a m e */ /******************************************************************************/ const char *XrdCmsUtils::SiteName(int snum) { XrdOucTList *sP = siteList; // Find matching site // while(sP && snum != sP->val) sP = sP->next; // Return result // return (sP ? sP->text : "anonymous"); }