Skip to content
Snippets Groups Projects
Commit 2c20bac7 authored by Steven Murray's avatar Steven Murray
Browse files

Improved VdqmConnectionHandler

parent 765a346e
Branches
Tags
No related merge requests found
......@@ -27,8 +27,6 @@
#include "castor/tape/tapeserver/daemon/VdqmAcceptHandler.hpp"
#include "castor/tape/tapeserver/daemon/VdqmConnectionHandler.hpp"
#include "castor/utils/SmartFd.hpp"
#include "h/common.h"
#include "h/serrno.h"
#include <errno.h>
#include <memory>
......@@ -56,6 +54,7 @@ castor::tape::tapeserver::daemon::VdqmAcceptHandler::VdqmAcceptHandler(
//------------------------------------------------------------------------------
castor::tape::tapeserver::daemon::VdqmAcceptHandler::~VdqmAcceptHandler()
throw() {
close(m_listenSock);
}
//------------------------------------------------------------------------------
......@@ -99,8 +98,9 @@ void castor::tape::tapeserver::daemon::VdqmAcceptHandler::handleEvent(
// Do nothing if there is no data to read
//
// POLLIN is not being used because on SLC5 it is not the logical or of
// POLLRDNORM and POLLRDBAND
// POLLIN is unfortuntaley not the logical or of POLLRDNORM and POLLRDBAND
// on SLC 5. I therefore replaced POLLIN with the logical or. I also
// added POLLPRI into the mix to cover all possible types of read event.
if(0 == (fd.revents & POLLRDNORM) && 0 == (fd.revents & POLLRDBAND) &&
0 == (fd.revents & POLLPRI)) {
return;
......@@ -119,42 +119,6 @@ void castor::tape::tapeserver::daemon::VdqmAcceptHandler::handleEvent(
m_log(LOG_DEBUG, "Accepted a possible vdqm connection");
// Close connection and return if connection is not from an admin host
{
// isadminhost fills in peerHost
char peerHost[CA_MAXHOSTNAMELEN+1];
memset(peerHost, '\0', sizeof(peerHost));
// Unfortunately isadminhost can either set errno or serrno
serrno = 0;
errno = 0;
const int rc = isadminhost(connection.get(), peerHost);
if(0 == rc) {
log::Param params[] = {
log::Param("host", peerHost[0] != '\0' ? peerHost : "UNKNOWN")};
m_log(LOG_INFO, "Received connection from authorized admin host", params);
} else {
// Give preference to serrno over errno when it comes to isadminhost()
const int savedErrno = errno;
const int savedSerrno = serrno;
std::string errorMessage;
if(0 != serrno) {
errorMessage = sstrerror(savedSerrno);
} else if(0 != errno) {
errorMessage = sstrerror(savedErrno);
} else {
errorMessage = "UNKNOWN";
}
log::Param params[] = {
log::Param("host", peerHost[0] != '\0' ? peerHost : "UNKNOWN"),
log::Param("message", errorMessage)};
m_log(LOG_ERR, "Failed to authorize vdqm host", params);
exception::Errnum::throwOnNegative(close(connection.release()),
"Failed to close unauthorized vdqm connection");
return;
}
}
// Create a new vdqm connection handler
std::auto_ptr<VdqmConnectionHandler> connectionHandler;
try {
......
......@@ -79,6 +79,8 @@ public:
/**
* Destructor.
*
* Closes the listen socket.
*/
~VdqmAcceptHandler() throw();
......
......@@ -21,6 +21,8 @@
*****************************************************************************/
#include "castor/tape/tapeserver/daemon/VdqmConnectionHandler.hpp"
#include "h/common.h"
#include "h/serrno.h"
//------------------------------------------------------------------------------
// constructor
......@@ -70,19 +72,95 @@ void castor::tape::tapeserver::daemon::VdqmConnectionHandler::fillPollFd(
//------------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::VdqmConnectionHandler::handleEvent(
const struct pollfd &fd) throw(castor::exception::Exception) {
checkHandleEventFd(fd.fd);
// Do nothing if there is not data to be read
if(0 == (fd.revents & POLLIN)) {
{
log::Param params[] = {
log::Param("POLLIN" , fd.revents & POLLIN ? "true" : "false"),
log::Param("POLLRDNORM", fd.revents & POLLRDNORM ? "true" : "false"),
log::Param("POLLRDBAND", fd.revents & POLLRDBAND ? "true" : "false"),
log::Param("POLLPRI" , fd.revents & POLLPRI ? "true" : "false"),
log::Param("POLLOUT" , fd.revents & POLLOUT ? "true" : "false"),
log::Param("POLLWRNORM", fd.revents & POLLWRNORM ? "true" : "false"),
log::Param("POLLWRBAND", fd.revents & POLLWRBAND ? "true" : "false"),
log::Param("POLLERR" , fd.revents & POLLERR ? "true" : "false"),
log::Param("POLLHUP" , fd.revents & POLLHUP ? "true" : "false"),
log::Param("POLLNVAL" , fd.revents & POLLNVAL ? "true" : "false")};
m_log(LOG_DEBUG, "VdqmConnectionHandler::handleEvent()", params);
}
// Do nothing if there is no data to read
//
// POLLIN is unfortuntaley not the logical or of POLLRDNORM and POLLRDBAND
// on SLC 5. I therefore replaced POLLIN with the logical or. I also
// added POLLPRI into the mix to cover all possible types of read event.
if(0 == (fd.revents & POLLRDNORM) && 0 == (fd.revents & POLLRDBAND) &&
0 == (fd.revents & POLLPRI)) {
return;
}
const legacymsg::RtcpJobRqstMsgBody job = readJobMsg(fd.fd);
logVdqmJobReception(job);
writeJobReplyMsg(fd.fd);
if(connectionIsAuthorized()) {
const legacymsg::RtcpJobRqstMsgBody job = readJobMsg(fd.fd);
logVdqmJobReception(job);
writeJobReplyMsg(fd.fd);
}
m_reactor.removeHandler(this);
}
//------------------------------------------------------------------------------
// checkHandleEventFd
//------------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::VdqmConnectionHandler::
checkHandleEventFd(const int fd) throw (castor::exception::Exception) {
if(m_connection != fd) {
castor::exception::Internal ex;
ex.getMessage() << "Failed to handle vdqm connection"
": Event handler passed wrong file descriptor"
": expected=" << m_connection << " actual=" << fd;
throw ex;
}
}
//------------------------------------------------------------------------------
// connectionIsAuthorized
//------------------------------------------------------------------------------
bool castor::tape::tapeserver::daemon::VdqmConnectionHandler::
connectionIsAuthorized() throw() {
// isadminhost fills in peerHost
char peerHost[CA_MAXHOSTNAMELEN+1];
memset(peerHost, '\0', sizeof(peerHost));
// Unfortunately isadminhost can either set errno or serrno
serrno = 0;
errno = 0;
const int rc = isadminhost(m_connection, peerHost);
if(0 == rc) {
log::Param params[] = {
log::Param("host", peerHost[0] != '\0' ? peerHost : "UNKNOWN")};
m_log(LOG_INFO, "Received connection from authorized admin host", params);
return true; // Connection is authorized
} else {
// Give preference to serrno over errno when it comes to isadminhost()
const int savedErrno = errno;
const int savedSerrno = serrno;
std::string errorMessage;
if(0 != serrno) {
errorMessage = sstrerror(savedSerrno);
} else if(0 != errno) {
errorMessage = sstrerror(savedErrno);
} else {
errorMessage = "UNKNOWN";
}
log::Param params[] = {
log::Param("host", peerHost[0] != '\0' ? peerHost : "UNKNOWN"),
log::Param("message", errorMessage)};
m_log(LOG_ERR, "Failed to authorize vdqm host", params);
return false; // Connection is not authorized
}
}
//------------------------------------------------------------------------------
// logVdqmJobReception
//------------------------------------------------------------------------------
......
......@@ -121,6 +121,18 @@ private:
*/
const int m_netTimeout;
/**
* Throws an exception if the specified file-descriptor is not that of the
* socket listening for connections from the vdqmd daemon.
*/
void checkHandleEventFd(const int fd) throw (castor::exception::Exception);
/**
* Returns true if the peer host of the connection being handled is
* authorized.
*/
bool connectionIsAuthorized() throw();
/**
* Logs the reception of the specified job message from the vdqmd daemon.
*/
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment