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;
190 {
const char *urName = addrInfo.
Name();
192 {
const char *dot = index(urName,
'.');
197 {
DBGID(client.
tident,
"Skipping sending flow info; unwanted domain");
205 if (!getCodes(client, path, cgi, eCode, aCode))
206 {
TRACE(
"Unable to determine experiment; flow not marked.");
213 {
const char *apP = strstr(cgi,
"pmark.appname=");
216 const char* aP = apP;
217 while(*aP && *aP !=
'&') aP++;
218 int apLen = aP - apP;
221 altApp.
insert(apP, 0, apLen);
222 app = altApp.
c_str();
254 if (pmFF->
Start(addrInfo))
return pmFF;
271 {
public: DelCfgInfo(
CfgInfo *&cfg) : cfgInfo(cfg) {}
272 ~DelCfgInfo() {
if (cfgInfo) {
delete cfgInfo; cfgInfo = 0;}}
299 eLog->
Say(
"Config warning: firefly disabled; "
300 "configuration incomplete!");
313 eLog->
Say(
"Config warning: ignoring defsfile; "
314 "no mappings have been specified!");
318 {
eLog->
Say(
"Config invalid: pmark mappings cannot be resolved "
319 "without specifying defsfile!");
329 eLog->
Say(
"Config warning: pmark ignoring defsfile; "
330 "unable to process and nofail is in effect!");
347 {snprintf(buff,
sizeof(buff),
"%s:%d; %s",
ffDest,
ffPortD, eTxt);
348 eLog->
Emsg(
"Config",
"pmark unable to create UDP tunnel to", buff);
353 if (spec.
Format(buff,
sizeof(buff)))
356 {
eLog->
Emsg(
"Config",
"pmark unable to create UDP tunnel to",
ffDest);
370 {
eLog->
Emsg(
"Config",
"pmark unable to create origin UDP tunnel");
386 else eDest->
Say(
"Config warning: Unable to determine local domain; "
387 " domain check restricted to IP address type!");
403 if (!
noFail)
return false;
409 bool XrdNetPMarkCfg::ConfigDefs()
414 Const2Char(
const char *str) : data(strdup(str)) {}
415 ~Const2Char() {free(data);}
418 std::set<std::string>::iterator it;
419 std::map<std::string, ExpInfo>::iterator itE;
420 bool isDload, aOK =
true;
437 if (!aOK)
return Recover();
442 {Const2Char pv(it->c_str());
443 if (!ConfigPV2E(pv.data)) aOK =
false;
450 {Const2Char ru(it->c_str());
451 if (!ConfigRU2A(ru.data)) aOK =
false;
459 while(itE !=
expMap.end())
460 {
if (itE->second.inUse)
461 {itE->second.Roles = itE->second.r2aMap.size() != 0;
462 itE->second.Users = itE->second.u2aMap.size() != 0;
465 DEBUG(
"Deleting unused experiment '"<<itE->first.c_str()<<
"'");
469 if (aOK &&
expMap.size() == 0)
472 {
eDest->
Say(
"Config warning: No experiments referenced; "
473 "packet marking restricted to scitagged url's!");
475 eDest->
Say(
"Config warning: No experiments referenced and scitags "
476 "not enabled; packet marking has been disabled!");
494 void Complain(
const char *rWho,
const char *rName,
495 const char *uWho,
const char *uName,
const char *eName=0)
497 char *et0P = 0, eText0[256], eText1[256], eText2[256];
499 {snprintf(eText0,
sizeof(eText0),
"experiment %s", eName);
502 snprintf(eText1,
sizeof(eText1),
"%s '%s'", rWho, rName);
503 snprintf(eText2,
sizeof(eText2),
"%s '%s'", uWho, uName);
504 eDest->
Say(
"Config failure: ",et0P, eText1,
" references undefined ",eText2);
510 bool XrdNetPMarkCfg::ConfigPV2E(
char *info)
512 std::map<std::string, ExpInfo >::iterator itE;
513 std::map<std::string, ExpInfo*>::iterator itV;
514 char *eName, *xName, *xType = info;
515 xName = index(info,
' '); *xName = 0; xName++;
516 eName = index(xName,
' '); *eName = 0; eName++;
518 if ((itE =
expMap.find(std::string(eName))) ==
expMap.end())
519 {Complain(xType, xName,
"experiment", eName);
522 itE->second.inUse =
true;
536 (xName, eName, &(itE->second)));
540 itV =
v2eMap.find(std::string(xName));
541 if (itV !=
v2eMap.end()) itV->second = &(itE->second);
542 else v2eMap[xName] = &(itE->second);
554 bool XrdNetPMarkCfg::ConfigRU2A(
char *info)
556 std::map<std::string, int>::iterator itA;
557 std::map<std::string, ExpInfo>::iterator itE;
558 std::map<std::string, MapInfo>::iterator itX;
559 char *aName, *eName, *xName, *xType;
561 xType = index(info,
' '); *xType = 0; xType++;
562 xName = index(xType,
' '); *xName = 0; xName++;
563 aName = index(xName,
' '); *aName = 0; aName++;
565 if ((itE =
expMap.find(std::string(eName))) ==
expMap.end())
566 {Complain(xType, xName,
"experiment", eName);
570 itA = itE->second.actMap.find(std::string(aName));
571 if (itA == itE->second.actMap.end())
572 {Complain(xType, xName,
"activity", aName, eName);
576 if (*xType ==
'd') itE->second.dAct = itA->second;
577 else {std::map<std::string, MapInfo> &xMap =
578 (*xType ==
'r' ? itE->second.r2aMap : itE->second.u2aMap);
580 itX = xMap.find(std::string(xName));
581 if (itX != xMap.end())
582 {itX->second.Name = aName; itX->second.Code = itA->second;}
583 else xMap[std::string(xName)] =
MapInfo(aName, itA->second);
595 const char *Code2S(
int code)
597 static char buff[16];
598 snprintf(buff,
sizeof(buff),
" [%d]", code);
602 void ShowActs(std::map<std::string, MapInfo>& map,
const char *hdr,
605 std::map<std::string, MapInfo>::iterator it;
607 for (it = map.begin(); it != map.end(); it++)
608 {
eDest->
Say(hdr, mName, it->first.c_str(),
" activity ",
609 it->second.Name.c_str(), Code2S(it->second.Code));
614 void XrdNetPMarkCfg::Display()
616 std::map<std::string, ExpInfo>::iterator itE;
617 std::map<int, std::vector<const char*>> pvRefs;
618 const char *hdr =
" ", *hdrplu =
" ++ ";
623 std::map<int, std::vector<const char*>>::iterator it2E;
628 if ((it2E = pvRefs.find(expinfo->
Code)) != pvRefs.end())
629 it2E->second.push_back(p2e->
thePath());
630 else {std::vector<const char*> vec;
632 pvRefs[expinfo->
Code] = vec;
639 std::map<std::string, ExpInfo*>::iterator itV;
641 {
int eCode = itV->second->Code;
642 if ((it2E = pvRefs.find(eCode)) != pvRefs.end())
643 it2E->second.push_back(itV->first.c_str());
644 else {std::vector<const char*> vec;
645 vec.push_back(itV->first.c_str());
653 snprintf(buff,
sizeof(buff),
"%d",
static_cast<int>(
expMap.size()));
654 const char *txt = (
expMap.size() == 1 ?
" expirement " :
" experiments ");
655 eDest->
Say(
"Config pmark results: ", buff, txt,
"directly referenced:");
660 {
int expCode = itE->second.Code;
661 eDest->
Say(hdr, itE->first.c_str(), Code2S(expCode),
662 (&itE->second ==
expDflt ?
" (default)" : 0));
663 if ((it2E = pvRefs.find(expCode)) != pvRefs.end())
664 {std::vector<const char*> &vec = it2E->second;
665 for (
int i = 0; i < (int)vec.size(); i++)
666 {
const char *rType = (*vec[i] ==
'/' ?
"path " :
"vorg ");
670 if (itE->second.u2aMap.size() != 0)
671 ShowActs(itE->second.u2aMap, hdrplu,
"user ");
672 if (itE->second.r2aMap.size() != 0)
673 ShowActs(itE->second.r2aMap, hdrplu,
"role ");
674 if (itE->second.dAct >= 0)
675 {std::map<std::string, int>::iterator itA;
676 int aCode = itE->second.dAct;
677 for (itA = itE->second.actMap.begin();
678 itA != itE->second.actMap.end(); itA++)
679 {
if (aCode == itA->second)
680 {
eDest->
Say(hdrplu,
"Default activity ",
681 itA->first.c_str(), Code2S(aCode));
685 if (itA == itE->second.actMap.end()) itE->second.dAct = -1;
694 const char *XrdNetPMarkCfg::Extract(
const char *sVec,
char *buff,
int blen)
700 if (!(space = index(sVec,
' ')))
return sVec;
704 int n = space - sVec;
705 if (!n || n >= blen)
return 0;
706 snprintf(buff, blen,
"%.*s", n, sVec);
714 bool XrdNetPMarkCfg::FetchFile()
718 char tmo[16], outfile[512];
724 {
eDest->
Emsg(
"Config", rc,
"setup job to fetch defsfile");
730 snprintf(outfile,
sizeof(outfile),
"/tmp/XrdPMark-%ld.json",
731 static_cast<long>(getpid()));
736 snprintf(tmo,
sizeof(tmo),
"%d",
Cfg->
defsTO);
753 {snprintf(outfile,
sizeof(outfile),
"failed with rc=%d", rc);
768 bool XrdNetPMarkCfg::getCodes(
XrdSecEntity &client,
const char *path,
769 const char *cgi,
int &ecode,
int &acode)
785 if (p2nP) expP = p2nP->
theValu();
791 {std::map<std::string, ExpInfo*>::iterator itV;
793 const char *VO = Extract(client.
vorg, voBuff,
sizeof(voBuff));
804 if (!expP)
return false;
810 {std::map<std::string, MapInfo>::iterator itU;
811 itU = expP->
u2aMap.find(std::string(client.
name));
812 if (itU != expP->
u2aMap.end())
813 {acode = itU->second.Code;
821 {std::map<std::string, MapInfo>::iterator itR;
823 const char *RO = Extract(client.
role, roBuff,
sizeof(roBuff));
825 {itR = expP->
r2aMap.find(std::string(client.
role));
826 if (itR != expP->
r2aMap.end())
827 {acode = itR->second.Code;
835 acode = (expP->
dAct >= 0 ? expP->
dAct : 0);
847 const char *MsgTrim(
const char *msg)
850 if ((sP = index(msg,
' ')) && *(sP+1))
return sP+1;
855 bool XrdNetPMarkCfg::LoadFile()
857 struct fBuff {
char *buff; fBuff() : buff(0) {}
858 ~fBuff() {
if (buff) free(buff);}
872 try {
bool result = LoadJson(defs.buff);
874 }
catch (json::exception& e)
875 {
eDest->
Emsg(
"Config",
"Unable to process defsfile;",
885 bool XrdNetPMarkCfg::LoadJson(
char *buff)
888 std::map<std::string, ExpInfo>::iterator itE;
892 j = json::parse(buff);
897 json j_mod = j[
"modified"];
898 if (j_mod != 0) modDate = j_mod.get<std::string>();
899 else modDate =
"*unspecified*";
902 "' last modified on ", modDate.c_str());
906 json j_exp = j[
"experiments"];
908 {
eDest->
Emsg(
"Config",
"The defsfile does not define any experiments!");
915 for (
auto it : j_exp)
916 {std::string expName = it[
"expName"].get<std::string>();
917 if (expName.empty())
continue;
918 if (!it[
"expId"].is_number() || it[
"expId"] < minExpID || it[
"expId"] > maxExpID)
919 {
eDest->
Say(
"Config warning: ignoring experiment '", expName.c_str(),
920 "'; associated ID is invalid.");
926 {
eDest->
Say(
"Config warning: ignoring experiment '", expName.c_str(),
927 "'; map insertion failed!");
931 json j_acts = it[
"activities"];
933 {
eDest->
Say(
"Config warning: ignoring experiment '", expName.c_str(),
934 "'; has no activities!");
938 for (
unsigned int i = 0; i < j_acts.size(); i++)
939 {std::string actName = j_acts[i][
"activityName"].get<std::string>();
940 if (actName.empty())
continue;
941 if (!j_acts[i][
"activityId"].is_number()
942 || j_acts[i][
"activityId"] < minActID
943 || j_acts[i][
"activityId"] > maxActID)
944 {
eDest->
Say(
"Config warning:",
"ignoring ", expName.c_str(),
945 " actitivity '", actName.c_str(),
946 "'; associated ID is invalid.");
949 itE->second.actMap[actName] = j_acts[i][
"activityId"].get<
int>();
956 {
eDest->
Say(
"Config warning: unable to define any experiments via defsfile!");
988 if (!(val =
Config.GetWord()))
989 {
eLog->
Say(
"Config invalid: pmark argument not specified");
return 1;}
993 do{
if (!strcmp(
"debug", val) || !strcmp(
"nodebug", val))
998 if (!strcmp(
"defsfile", val))
999 {
if (!(val =
Config.GetWord()))
1000 {
eLog->
Say(
"Config invalid: pmark defsfile value not specified");
1004 if (!strcmp(
"fail", val) || !strcmp(
"nofail", val))
1006 if (!(val =
Config.GetWord()))
1007 {
eLog->
Say(
"Config invalid: pmark defsfile locationnot specified");
1017 if (strcmp(
"curl", val) && strcmp(
"wget", val))
1018 {
eLog->
Say(
"Config invalid: unknown defsfile transfer agent '",val,
"'");
1022 {
eLog->
Say(
"Config invalid: defsfile transfer agent '",val,
"' not found.");
1033 if (val && isdigit(*val))
1039 if (!val) {
eLog->
Say(
"Config invalid: pmark defsfile url not specified");
1046 if (!strcmp(
"domain", val))
1047 {
if (!(val =
Config.GetWord()))
1048 {
eLog->
Say(
"Config invalid: pmark domain value not specified");
1051 if (!strcmp(val,
"any" )
1055 else {
eLog->
Say(
"Config invalid: pmark invalid domain determinant '",
1062 if (!strcmp(
"fail", val) || !strcmp(
"nofail", val))
1070 if (!strcmp(
"ffdest", val))
1071 {
const char *addtxt =
"";
1072 char *colon, *comma;
1075 do {
if (!val || *val == 0 || *val ==
',' || *val ==
':')
1076 {
eLog->
Say(
"Config invalid: pmark ffdest value not specified",
1079 if ((comma = index(val,
','))) *comma++ = 0;
1080 if ((colon = index(val,
':')))
1085 if (!strcmp(val,
"origin"))
ffPortO = xPort;
1090 addtxt =
" after comma";
1091 }
while((val = comma));
1096 if (!strcmp(
"ffecho", val))
1097 {
if (!(val =
Config.GetWord()))
1098 {
eLog->
Say(
"Config invalid: pmark ffecho value not specified");
1106 if (!strcmp(
"map2act", val))
1107 {
if (!(val =
Config.GetWord()))
1108 {
eLog->
Say(
"Config invalid: pmark activity experiment not specified");
1113 if (!(val =
Config.GetWord()))
1114 {
eLog->
Say(
"Config invalid: pmark activity determinant not specified");
1119 if (!strcmp(val,
"default")) adet =
"dflt";
1120 else if (!strcmp(val,
"role")) adet =
"role";
1121 else if (!strcmp(val,
"user")) adet =
"user";
1122 else {
eLog->
Say(
"Config invalid: pmark invalid activity determinant '",
1126 name +=
' '; name += val;
1128 if (*adet !=
'd' && !(val =
Config.GetWord()))
1129 {
eLog->
Say(
"Config invalid: pmark activity", adet,
"not specified");
1132 name +=
' '; name += val;
1134 if (!(val =
Config.GetWord()))
1135 {
eLog->
Say(
"Config invalid: pmark", adet,
"activity not specified");
1138 name +=
' '; name += val;
1144 if (!strcmp(
"map2exp", val))
1145 {
if (!(val =
Config.GetWord()))
1146 {
eLog->
Say(
"Config invalid: pmark map2exp type not specified");
1149 if (strcmp(
"default", val) && strcmp(
"path", val)
1150 && strcmp(
"vo", val) && strcmp(
"vorg", val))
1151 {
eLog->
Say(
"Config invalid: invalid pmark map2exp type, '",val,
"'.");
1156 if (*val !=
'd' && !(val =
Config.GetWord()))
1157 {
eLog->
Say(
"Config invalid: pmark map2exp ", name.c_str(),
1161 name +=
' '; name += val;
1163 if (!(val =
Config.GetWord()))
1164 {
eLog->
Say(
"Config invalid: pmark map2exp expirement not specified");
1167 name +=
' '; name += val;
1173 if (!strcmp(
"trace", val) || !strcmp(
"notrace", val))
1178 if (!strcmp(
"use", val))
1179 {
if (!(val =
Config.GetWord()))
1180 {
eLog->
Say(
"Config invalid: pmark use argument not specified");
1185 do {
bool theval = strncmp(val,
"no", 2) != 0;
1186 arg = (!theval ? val += 2 : val);
1187 if (!strcmp(
"flowlabel", arg))
1189 else if (!strcmp(
"flowlabel+ff", arg))
1191 else if (!strcmp(
"firefly", arg))
1192 {
useFFly = (theval ? 1 : 0); argOK =
true;}
1193 else if (!strcmp(
"scitag", arg)) {
useSTag = theval; argOK =
true;}
1194 else if (argOK) {
Config.RetToken();
break;}
1195 else {
eLog->
Say(
"Config invalid: 'use ",val,
"' is invalid");
1198 }
while((val =
Config.GetWord()));
1203 eLog->
Say(
"Config warning: ignoring unknown pmark argument'",val,
"'.");
1205 }
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()
void insert(const int i, int start=-1)
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