Skip to content

Commit

Permalink
Enforce prepare limits.
Browse files Browse the repository at this point in the history
  • Loading branch information
bbockelm committed Jan 19, 2017
1 parent 7fae207 commit 6e1e8bd
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 0 deletions.
40 changes: 40 additions & 0 deletions src/XrdXrootd/XrdXrootdConfig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@ int XrdXrootdProtocol::Config(const char *ConfigFN)
else if TS_Xeq("redirect", xred);
else if TS_Xeq("seclib", xsecl);
else if TS_Xeq("trace", xtrace);
else if TS_Xeq("limit", xlimit);
else {eDest.Say("Config warning: ignoring unknown directive '",var,"'.");
Config.Echo();
continue;
Expand Down Expand Up @@ -1547,3 +1548,42 @@ int XrdXrootdProtocol::xtrace(XrdOucStream &Config)
XrdXrootdTrace->What = trval;
return 0;
}

/******************************************************************************/
/* x l i m i t */
/******************************************************************************/

/* Function: xlimit
Purpose: To parse the directive: limit [prepare <count>] [noerror]
prepare <count> The maximum number of prepares that are allowed
during the course of a single connection
noerror When possible, do not issue an error when a limit
is hit.
Output: 0 upon success or 1 upon failure.
*/
int XrdXrootdProtocol::xlimit(XrdOucStream &Config)
{
int plimit = -1;
const char *word;

// Look for various limits set
//
while ( (word = Config.GetWord()) ) {
if (!strcmp(word, "prepare")) {
if (!(word = Config.GetWord()))
{
eDest.Emsg("Config", "'limit prepare' value not specified");
return 1;
}
if (XrdOuca2x::a2i(eDest, "limit prepare", word, &plimit, 0)) { return 1; }
} else if (!strcmp(word, "noerror")) {
LimitError = false;
}
}
if (plimit >= 0) {PrepareLimit = plimit;}
return 0;
}
4 changes: 4 additions & 0 deletions src/XrdXrootd/XrdXrootdProtocol.cc
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ int XrdXrootdProtocol::myPID = static_cast<int>(getpid());
int XrdXrootdProtocol::myRole = 0;
int XrdXrootdProtocol::myRolf = 0;

int XrdXrootdProtocol::PrepareLimit = -1;
bool XrdXrootdProtocol::LimitError = true;

struct XrdXrootdProtocol::RD_Table XrdXrootdProtocol::Route[RD_Num];

/******************************************************************************/
Expand Down Expand Up @@ -846,4 +849,5 @@ void XrdXrootdProtocol::Reset()
rdType = 0;
memset(&Entity, 0, sizeof(Entity));
memset(Stream, 0, sizeof(Stream));
PrepareCount = 0;
}
8 changes: 8 additions & 0 deletions src/XrdXrootd/XrdXrootdProtocol.hh
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ static void xred_set(RD_func func, char *rHost[2], int rPort[2]);
static bool xred_xok(int func, char *rHost[2], int rPort[2]);
static int xsecl(XrdOucStream &Config);
static int xtrace(XrdOucStream &Config);
static int xlimit(XrdOucStream &Config);

static XrdObjectQ<XrdXrootdProtocol> ProtStack;
XrdObject<XrdXrootdProtocol> ProtLink;
Expand Down Expand Up @@ -389,6 +390,13 @@ char doWrite;
char doWriteC;
char rvSeq;

// Track usage limts.
//
static bool LimitError; // Indicates that hitting a limit should result in an error response.
// If false, when possible, silently ignore errors.
int PrepareCount;
static int PrepareLimit;

// Buffers to handle client requests
//
XrdXrootdReqID ReqID;
Expand Down
10 changes: 10 additions & 0 deletions src/XrdXrootd/XrdXrootdXeq.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1416,6 +1416,16 @@ int XrdXrootdProtocol::do_Prepare()
XrdXrootdPrepArgs pargs(0, 0);
XrdSfsPrep fsprep;

// Apply prepare limits, as necessary.
if ((PrepareLimit >= 0) && (++PrepareCount > PrepareLimit)) {
if (LimitError) {
return Response.Send(kXR_noserver,
"Surpassed this connection's prepare limit.");
} else {
return Response.Send();
}
}

// Grab the options
//
opts = Request.prepare.options;
Expand Down

0 comments on commit 6e1e8bd

Please sign in to comment.