#include "remoting/impl/SocketListener.h"
#include "util/IPRange.h"
+#include <boost/bind.hpp>
+#include <boost/algorithm/string.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xmltooling/unicode.h>
#include <xmltooling/util/XMLHelper.h>
using namespace shibsp;
using namespace xmltooling;
using namespace xercesc;
+using namespace boost;
using namespace std;
namespace shibsp {
m_port = 1600;
}
- int j = 0;
+ vector<string> rawacls;
string aclbuf = XMLHelper::getAttrString(e, "127.0.0.1", acl);
- for (unsigned int i = 0; i < aclbuf.length(); ++i) {
- if (aclbuf.at(i) == ' ') {
- try {
- m_acl.push_back(IPRange::parseCIDRBlock(aclbuf.substr(j, i-j).c_str()));
- }
- catch (exception& ex) {
- log->error("invalid CIDR block (%s): %s", aclbuf.substr(j, i-j).c_str(), ex.what());
- }
- j = i + 1;
+ boost::split(rawacls, aclbuf, boost::is_space(), algorithm::token_compress_on);
+ for (vector<string>::const_iterator i = rawacls.begin(); i < rawacls.end(); ++i) {
+ try {
+ m_acl.push_back(IPRange::parseCIDRBlock(i->c_str()));
+ }
+ catch (std::exception& ex) {
+ log->error("invalid CIDR block (%s): %s", i->c_str(), ex.what());
}
- }
- try {
- m_acl.push_back(IPRange::parseCIDRBlock(aclbuf.substr(j, aclbuf.length()-j).c_str()));
- }
- catch (exception& ex) {
- log->error("invalid CIDR block (%s): %s", aclbuf.substr(j, aclbuf.length()-j).c_str(), ex.what());
}
if (m_acl.empty()) {
::setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt));
#ifdef WIN32
- if (SOCKET_ERROR==::bind(s, (const struct sockaddr*)&m_sockaddr, m_sockaddr.ss_len) || SOCKET_ERROR==::listen(s, 3)) {
+ if (SOCKET_ERROR==::bind(s, (const struct sockaddr*)&m_sockaddr, sizeof(m_sockaddr)) || SOCKET_ERROR==::listen(s, 3)) {
log_error("bind");
close(s);
return false;
}
#else
-# ifdef HAVE_STRUCT_SOCKADDR_STORAGE
- if (::bind(s, (const struct sockaddr*)&m_sockaddr, m_sockaddr.ss_len) < 0)
+ // Newer BSDs require the struct length be passed based on the socket address.
+ // Others have no field for that and take the whole struct size like Windows does.
+# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+# ifdef HAVE_STRUCT_SOCKADDR_STORAGE
+ if (::bind(s, (const struct sockaddr*)&m_sockaddr, m_sockaddr.ss_len) < 0) {
+# else
+ if (::bind(s, (const struct sockaddr*)&m_sockaddr, m_sockaddr.sin_len) < 0) {
+# endif
# else
- if (::bind(s, (const struct sockaddr*)&m_sockaddr, m_sockaddr.sin_len) < 0)
+ if (::bind(s, (const struct sockaddr*)&m_sockaddr, sizeof(m_sockaddr)) < 0) {
# endif
- {
log_error("bind");
close(s);
return false;
bool TCPListener::connect(ShibSocket& s) const
{
#ifdef WIN32
- if(SOCKET_ERROR==::connect(s, (const struct sockaddr*)&m_sockaddr, m_sockaddr.ss_len))
+ if(SOCKET_ERROR==::connect(s, (const struct sockaddr*)&m_sockaddr, sizeof(m_sockaddr)))
return log_error("connect");
#else
-# ifdef HAVE_STRUCT_SOCKADDR_STORAGE
+ // Newer BSDs require the struct length be passed based on the socket address.
+ // Others have no field for that and take the whole struct size like Windows does.
+# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+# ifdef HAVE_STRUCT_SOCKADDR_STORAGE
if (::connect(s, (const struct sockaddr*)&m_sockaddr, m_sockaddr.ss_len) < 0)
-# else
+# else
if (::connect(s, (const struct sockaddr*)&m_sockaddr, m_sockaddr.sin_len) < 0)
+# endif
+# else
+ if (::connect(s, (const struct sockaddr*)&m_sockaddr, sizeof(m_sockaddr)) < 0)
# endif
return log_error("connect");
#endif
if (s < 0)
#endif
return log_error("accept");
- bool found = false;
- for (vector<IPRange>::const_iterator acl = m_acl.begin(); !found && acl != m_acl.end(); ++acl) {
- found = acl->contains((const struct sockaddr*)&addr);
- }
- if (!found) {
+
+ static bool (IPRange::* contains)(const struct sockaddr*) const = &IPRange::contains;
+ if (find_if(m_acl.begin(), m_acl.end(), boost::bind(contains, _1, (const struct sockaddr*)&addr)) == m_acl.end()) {
close(s);
s = -1;
log->error("accept() rejected client with invalid address");