39 #include <sys/types.h>
46 #include "XrdOuc/XrdOucJson.hh"
63 if (doTrace) SYSTRACE(Trace->, client.tident, epName, 0, txt)
66 if (doDebug) SYSTRACE(Trace->, 0, epName, 0, txt)
68 #define DBGID(tid, txt) \
69 if (doDebug) SYSTRACE(Trace->, tid, epName, 0, txt)
71 #define EPName(ep) const char *epName = ep
92 std::map<std::string, MapInfo>
r2aMap;
93 std::map<std::string, MapInfo>
u2aMap;
189 {
const char *urName = addrInfo.
Name();
191 {
const char *dot = index(urName,
'.');
196 {
DBGID(client.
tident,
"Skipping sending flow info; unwanted domain");
204 if (!getCodes(client, path, cgi, eCode, aCode))
205 {
TRACE(
"Unable to determine experiment; flow not marked.");
236 if (pmFF->
Start(addrInfo))
return pmFF;
253 {
public: DelCfgInfo(
CfgInfo *&cfg) : cfgInfo(cfg) {}
254 ~DelCfgInfo() {
if (cfgInfo) {
delete cfgInfo; cfgInfo = 0;}}
281 eLog->
Say(
"Config warning: firefly disabled; "
282 "configuration incomplete!");
295 eLog->
Say(
"Config warning: ignoring defsfile; "
296 "no mappings have been specified!");
300 {
eLog->
Say(
"Config invalid: pmark mappings cannot be resolved "
301 "without specifying defsfile!");
311 eLog->
Say(
"Config warning: pmark ignoring defsfile; "
312 "unable to process and nofail is in effect!");
329 {snprintf(buff,
sizeof(buff),
"%s:%d; %s",
ffDest,
ffPortD, eTxt);
330 eLog->
Emsg(
"Config",
"pmark unable to create UDP tunnel to", buff);
335 if (spec.
Format(buff,
sizeof(buff)))
338 {
eLog->
Emsg(
"Config",
"pmark unable to create UDP tunnel to",
ffDest);
352 {
eLog->
Emsg(
"Config",
"pmark unable to create origin UDP tunnel");
368 else eDest->
Say(
"Config warning: Unable to determine local domain; "
369 " domain check restricted to IP address type!");
385 if (!
noFail)
return false;
391 bool XrdNetPMarkCfg::ConfigDefs()
396 Const2Char(
const char *str) : data(strdup(str)) {}
397 ~Const2Char() {free(data);}
400 std::set<std::string>::iterator it;
401 std::map<std::string, ExpInfo>::iterator itE;
402 bool isDload, aOK =
true;
419 if (!aOK)
return Recover();
424 {Const2Char pv(it->c_str());
425 if (!ConfigPV2E(pv.data)) aOK =
false;
432 {Const2Char ru(it->c_str());
433 if (!ConfigRU2A(ru.data)) aOK =
false;
441 while(itE !=
expMap.end())
442 {
if (itE->second.inUse)
443 {itE->second.Roles = itE->second.r2aMap.size() != 0;
444 itE->second.Users = itE->second.u2aMap.size() != 0;
447 DEBUG(
"Deleting unused experiment '"<<itE->first.c_str()<<
"'");
451 if (aOK &&
expMap.size() == 0)
454 {
eDest->
Say(
"Config warning: No experiments referenced; "
455 "packet marking restricted to scitagged url's!");
457 eDest->
Say(
"Config warning: No experiments referenced and scitags "
458 "not enabled; packet marking has been disabled!");
476 void Complain(
const char *rWho,
const char *rName,
477 const char *uWho,
const char *uName,
const char *eName=0)
479 char *et0P = 0, eText0[256], eText1[256], eText2[256];
481 {snprintf(eText0,
sizeof(eText0),
"experiment %s", eName);
484 snprintf(eText1,
sizeof(eText1),
"%s '%s'", rWho, rName);
485 snprintf(eText2,
sizeof(eText2),
"%s '%s'", uWho, uName);
486 eDest->
Say(
"Config failure: ",et0P, eText1,
" references undefined ",eText2);
492 bool XrdNetPMarkCfg::ConfigPV2E(
char *info)
494 std::map<std::string, ExpInfo >::iterator itE;
495 std::map<std::string, ExpInfo*>::iterator itV;
496 char *eName, *xName, *xType = info;
497 xName = index(info,
' '); *xName = 0; xName++;
498 eName = index(xName,
' '); *eName = 0; eName++;
500 if ((itE =
expMap.find(std::string(eName))) ==
expMap.end())
501 {Complain(xType, xName,
"experiment", eName);
504 itE->second.inUse =
true;
518 (xName, eName, &(itE->second)));
522 itV =
v2eMap.find(std::string(xName));
523 if (itV !=
v2eMap.end()) itV->second = &(itE->second);
524 else v2eMap[xName] = &(itE->second);
536 bool XrdNetPMarkCfg::ConfigRU2A(
char *info)
538 std::map<std::string, int>::iterator itA;
539 std::map<std::string, ExpInfo>::iterator itE;
540 std::map<std::string, MapInfo>::iterator itX;
541 char *aName, *eName, *xName, *xType;
543 xType = index(info,
' '); *xType = 0; xType++;
544 xName = index(xType,
' '); *xName = 0; xName++;
545 aName = index(xName,
' '); *aName = 0; aName++;
547 if ((itE =
expMap.find(std::string(eName))) ==
expMap.end())
548 {Complain(xType, xName,
"experiment", eName);
552 itA = itE->second.actMap.find(std::string(aName));
553 if (itA == itE->second.actMap.end())
554 {Complain(xType, xName,
"activity", aName, eName);
558 if (*xType ==
'd') itE->second.dAct = itA->second;
559 else {std::map<std::string, MapInfo> &xMap =
560 (*xType ==
'r' ? itE->second.r2aMap : itE->second.u2aMap);
562 itX = xMap.find(std::string(xName));
563 if (itX != xMap.end())
564 {itX->second.Name = aName; itX->second.Code = itA->second;}
565 else xMap[std::string(xName)] =
MapInfo(aName, itA->second);
577 const char *Code2S(
int code)
579 static char buff[16];
580 snprintf(buff,
sizeof(buff),
" [%d]", code);
584 void ShowActs(std::map<std::string, MapInfo>& map,
const char *hdr,
587 std::map<std::string, MapInfo>::iterator it;
589 for (it = map.begin(); it != map.end(); it++)
590 {
eDest->
Say(hdr, mName, it->first.c_str(),
" activity ",
591 it->second.Name.c_str(), Code2S(it->second.Code));
596 void XrdNetPMarkCfg::Display()
598 std::map<std::string, ExpInfo>::iterator itE;
599 std::map<int, std::vector<const char*>> pvRefs;
600 const char *hdr =
" ", *hdrplu =
" ++ ";
605 std::map<int, std::vector<const char*>>::iterator it2E;
610 if ((it2E = pvRefs.find(expinfo->
Code)) != pvRefs.end())
611 it2E->second.push_back(p2e->
thePath());
612 else {std::vector<const char*> vec;
614 pvRefs[expinfo->
Code] = vec;
621 std::map<std::string, ExpInfo*>::iterator itV;
623 {
int eCode = itV->second->Code;
624 if ((it2E = pvRefs.find(eCode)) != pvRefs.end())
625 it2E->second.push_back(itV->first.c_str());
626 else {std::vector<const char*> vec;
627 vec.push_back(itV->first.c_str());
635 snprintf(buff,
sizeof(buff),
"%d",
static_cast<int>(
expMap.size()));
636 const char *txt = (
expMap.size() == 1 ?
" expirement " :
" experiments ");
637 eDest->
Say(
"Config pmark results: ", buff, txt,
"directly referenced:");
642 {
int expCode = itE->second.Code;
643 eDest->
Say(hdr, itE->first.c_str(), Code2S(expCode),
644 (&itE->second ==
expDflt ?
" (default)" : 0));
645 if ((it2E = pvRefs.find(expCode)) != pvRefs.end())
646 {std::vector<const char*> &vec = it2E->second;
647 for (
int i = 0; i < (int)vec.size(); i++)
648 {
const char *rType = (*vec[i] ==
'/' ?
"path " :
"vorg ");
652 if (itE->second.u2aMap.size() != 0)
653 ShowActs(itE->second.u2aMap, hdrplu,
"user ");
654 if (itE->second.r2aMap.size() != 0)
655 ShowActs(itE->second.r2aMap, hdrplu,
"role ");
656 if (itE->second.dAct >= 0)
657 {std::map<std::string, int>::iterator itA;
658 int aCode = itE->second.dAct;
659 for (itA = itE->second.actMap.begin();
660 itA != itE->second.actMap.end(); itA++)
661 {
if (aCode == itA->second)
662 {
eDest->
Say(hdrplu,
"Default activity ",
663 itA->first.c_str(), Code2S(aCode));
667 if (itA == itE->second.actMap.end()) itE->second.dAct = -1;
676 const char *XrdNetPMarkCfg::Extract(
const char *sVec,
char *buff,
int blen)
682 if (!(space = index(sVec,
' ')))
return sVec;
686 int n = space - sVec;
687 if (!n || n >= blen)
return 0;
688 snprintf(buff, blen,
"%.*s", n, sVec);
696 bool XrdNetPMarkCfg::FetchFile()
700 char tmo[16], outfile[512];
706 {
eDest->
Emsg(
"Config", rc,
"setup job to fetch defsfile");
712 snprintf(outfile,
sizeof(outfile),
"/tmp/XrdPMark-%ld.json",
713 static_cast<long>(getpid()));
718 snprintf(tmo,
sizeof(tmo),
"%d",
Cfg->
defsTO);
735 {snprintf(outfile,
sizeof(outfile),
"failed with rc=%d", rc);
750 bool XrdNetPMarkCfg::getCodes(
XrdSecEntity &client,
const char *path,
751 const char *cgi,
int &ecode,
int &acode)
767 if (p2nP) expP = p2nP->
theValu();
773 {std::map<std::string, ExpInfo*>::iterator itV;
775 const char *VO = Extract(client.
vorg, voBuff,
sizeof(voBuff));
786 if (!expP)
return false;
792 {std::map<std::string, MapInfo>::iterator itU;
793 itU = expP->
u2aMap.find(std::string(client.
name));
794 if (itU != expP->
u2aMap.end())
795 {acode = itU->second.Code;
803 {std::map<std::string, MapInfo>::iterator itR;
805 const char *RO = Extract(client.
role, roBuff,
sizeof(roBuff));
807 {itR = expP->
r2aMap.find(std::string(client.
role));
808 if (itR != expP->
r2aMap.end())
809 {acode = itR->second.Code;
817 acode = (expP->
dAct >= 0 ? expP->
dAct : 0);
829 const char *MsgTrim(
const char *msg)
832 if ((sP = index(msg,
' ')) && *(sP+1))
return sP+1;
837 bool XrdNetPMarkCfg::LoadFile()
839 struct fBuff {
char *buff; fBuff() : buff(0) {}
840 ~fBuff() {
if (buff) free(buff);}
854 try {
bool result = LoadJson(defs.buff);
856 }
catch (json::exception& e)
857 {
eDest->
Emsg(
"Config",
"Unable to process defsfile;",
867 bool XrdNetPMarkCfg::LoadJson(
char *buff)
870 std::map<std::string, ExpInfo>::iterator itE;
874 j = json::parse(buff);
879 json j_mod = j[
"modified"];
880 if (j_mod != 0) modDate = j_mod.get<std::string>();
881 else modDate =
"*unspecified*";
884 "' last modified on ", modDate.c_str());
888 json j_exp = j[
"experiments"];
890 {
eDest->
Emsg(
"Config",
"The defsfile does not define any experiments!");
897 for (
auto it : j_exp)
898 {std::string expName = it[
"expName"].get<std::string>();
899 if (expName.empty())
continue;
900 if (!it[
"expId"].is_number() || it[
"expId"] < minExpID || it[
"expId"] > maxExpID)
901 {
eDest->
Say(
"Config warning: ignoring experiment '", expName.c_str(),
902 "'; associated ID is invalid.");
908 {
eDest->
Say(
"Config warning: ignoring experiment '", expName.c_str(),
909 "'; map insertion failed!");
913 json j_acts = it[
"activities"];
915 {
eDest->
Say(
"Config warning: ignoring experiment '", expName.c_str(),
916 "'; has no activities!");
920 for (
unsigned int i = 0; i < j_acts.size(); i++)
921 {std::string actName = j_acts[i][
"activityName"].get<std::string>();
922 if (actName.empty())
continue;
923 if (!j_acts[i][
"activityId"].is_number()
924 || j_acts[i][
"activityId"] < minActID
925 || j_acts[i][
"activityId"] > maxActID)
926 {
eDest->
Say(
"Config warning:",
"ignoring ", expName.c_str(),
927 " actitivity '", actName.c_str(),
928 "'; associated ID is invalid.");
931 itE->second.actMap[actName] = j_acts[i][
"activityId"].get<
int>();
938 {
eDest->
Say(
"Config warning: unable to define any experiments via defsfile!");
970 if (!(val =
Config.GetWord()))
971 {
eLog->
Say(
"Config invalid: pmark argument not specified");
return 1;}
975 do{
if (!strcmp(
"debug", val) || !strcmp(
"nodebug", val))
980 if (!strcmp(
"defsfile", val))
981 {
if (!(val =
Config.GetWord()))
982 {
eLog->
Say(
"Config invalid: pmark defsfile value not specified");
991 if (strcmp(
"curl", val) && strcmp(
"wget", val))
992 {
eLog->
Say(
"Config invalid: unknown defsfile transfer agent '",val,
"'");
996 {
eLog->
Say(
"Config invalid: defsfile transfer agent '",val,
"' not found.");
1007 if (val && isdigit(*val))
1013 if (!val) {
eLog->
Say(
"Config invalid: pmark defsfile url not specified");
1020 if (!strcmp(
"domain", val))
1021 {
if (!(val =
Config.GetWord()))
1022 {
eLog->
Say(
"Config invalid: pmark domain value not specified");
1025 if (!strcmp(val,
"any" )
1029 else {
eLog->
Say(
"Config invalid: pmark invalid domain determinant '",
1036 if (!strcmp(
"fail", val) || !strcmp(
"nofail", val))
1044 if (!strcmp(
"ffdest", val))
1045 {
const char *addtxt =
"";
1046 char *colon, *comma;
1049 do {
if (!val || *val == 0 || *val ==
',' || *val ==
':')
1050 {
eLog->
Say(
"Config invalid: pmark ffdest value not specified",
1053 if ((comma = index(val,
','))) *comma++ = 0;
1054 if ((colon = index(val,
':')))
1059 if (!strcmp(val,
"origin"))
ffPortO = xPort;
1064 addtxt =
" after comma";
1065 }
while((val = comma));
1070 if (!strcmp(
"ffecho", val))
1071 {
if (!(val =
Config.GetWord()))
1072 {
eLog->
Say(
"Config invalid: pmark ffecho value not specified");
1080 if (!strcmp(
"map2act", val))
1081 {
if (!(val =
Config.GetWord()))
1082 {
eLog->
Say(
"Config invalid: pmark activity experiment not specified");
1087 if (!(val =
Config.GetWord()))
1088 {
eLog->
Say(
"Config invalid: pmark activity determinant not specified");
1093 if (!strcmp(val,
"default")) adet =
"dflt";
1094 else if (!strcmp(val,
"role")) adet =
"role";
1095 else if (!strcmp(val,
"user")) adet =
"user";
1096 else {
eLog->
Say(
"Config invalid: pmark invalid activity determinant '",
1100 name +=
' '; name += val;
1102 if (*adet !=
'd' && !(val =
Config.GetWord()))
1103 {
eLog->
Say(
"Config invalid: pmark activity", adet,
"not specified");
1106 name +=
' '; name += val;
1108 if (!(val =
Config.GetWord()))
1109 {
eLog->
Say(
"Config invalid: pmark", adet,
"activity not specified");
1112 name +=
' '; name += val;
1118 if (!strcmp(
"map2exp", val))
1119 {
if (!(val =
Config.GetWord()))
1120 {
eLog->
Say(
"Config invalid: pmark map2exp type not specified");
1123 if (strcmp(
"default", val) && strcmp(
"path", val)
1124 && strcmp(
"vo", val) && strcmp(
"vorg", val))
1125 {
eLog->
Say(
"Config invalid: invalid pmark map2exp type, '",val,
"'.");
1130 if (*val !=
'd' && !(val =
Config.GetWord()))
1131 {
eLog->
Say(
"Config invalid: pmark map2exp ", name.c_str(),
1135 name +=
' '; name += val;
1137 if (!(val =
Config.GetWord()))
1138 {
eLog->
Say(
"Config invalid: pmark map2exp expirement not specified");
1141 name +=
' '; name += val;
1147 if (!strcmp(
"trace", val) || !strcmp(
"notrace", val))
1152 if (!strcmp(
"use", val))
1153 {
if (!(val =
Config.GetWord()))
1154 {
eLog->
Say(
"Config invalid: pmark use argument not specified");
1159 do {
bool theval = strncmp(val,
"no", 2) != 0;
1160 arg = (!theval ? val += 2 : val);
1161 if (!strcmp(
"flowlabel", arg))
1163 else if (!strcmp(
"flowlabel+ff", arg))
1165 else if (!strcmp(
"firefly", arg))
1166 {
useFFly = (theval ? 1 : 0); argOK =
true;}
1167 else if (!strcmp(
"scitag", arg)) {
useSTag = theval; argOK =
true;}
1168 else if (argOK) {
Config.RetToken();
break;}
1169 else {
eLog->
Say(
"Config invalid: 'use ",val,
"' is invalid");
1172 }
while((val =
Config.GetWord()));
1177 eLog->
Say(
"Config warning: ignoring unknown pmark argument'",val,
"'.");
1179 }
while ((val =
Config.GetWord()));
int unlink(const char *path)
static bool isHostName(const char *name)
int Format(char *bAddr, int bLen, fmtUse fmtType=fmtAuto, int fmtOpts=0)
const char * Name(const char *eName=0, const char **eText=0)
const char * Set(const char *hSpec, int pNum=PortInSpec)
static int Parse(XrdSysError *eLog, XrdOucStream &Config)
static XrdNetPMark * Config(XrdSysError *eLog, XrdScheduler *sched, XrdSysTrace *trc, bool &fatal)
XrdNetPMark::Handle * Begin(XrdSecEntity &Client, const char *path=0, const char *cgi=0, const char *app=0) override
std::map< std::string, int > actMap
std::map< std::string, MapInfo > u2aMap
std::map< std::string, MapInfo > r2aMap
MapInfo(const char *name, int code)
bool Start(XrdNetAddrInfo &addr)
static bool getEA(const char *cgi, int &ecode, int &acode)
static char * MyHostName(const char *eName="*unknown*", const char **eText=0)
void RepName(const char *newname)
XrdOucMapP2X< T > * theNext()
const char * c_str() const
static bool findPgm(const char *pgm, XrdOucString &path)
static char * getFile(const char *path, int &rc, int maxsz=10240, bool notempty=true)
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
static int a2p(XrdSysError &, const char *ptype, const char *val, bool anyOK=true)
char * vorg
Entity's virtual organization(s)
XrdNetAddrInfo * addrInfo
Entity's connection details.
const char * tident
Trace identifier always preset.
char * name
Entity's name.
char * role
Entity's role(s)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
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)
std::map< std::string, ExpInfo > expMap
std::map< std::string, ExpInfo * > v2eMap
XrdOucMapP2X< ExpInfo * > p2eMap
std::set< std::string > x2eSet
const char * pgmOpts[pgmOptN]
std::set< std::string > x2aSet