return 0;
}
+typedef std::map<std::string, Config::ReturnCode> Codes;
+
+// One-time call to initialize the list of codes.
+Codes getCodes()
+{
+ Codes res;
+ res["reject"] = Config::REJECT;
+ res["fail"] = Config::FAIL;
+ res["ok"] = Config::OK;
+ res["handled"] = Config::HANDLED;
+ res["invalid"] = Config::INVALID;
+ res["userlock"] = Config::USERLOCK;
+ res["notfound"] = Config::NOTFOUND;
+ res["noop"] = Config::NOOP;
+ res["updated"] = Config::UPDATED;
+ return res;
+}
+
+Config::ReturnCode toReturnCode(const std::vector<std::string>& values)
+{
+ static Codes codes(getCodes());
+ if (values.empty())
+ return Config::REJECT;
+ std::string code = ToLower(values[0]);
+ const Codes::const_iterator it = codes.find(code);
+ if (it == codes.end())
+ return Config::REJECT;
+ return it->second;
+}
+
Config::Pairs parseVector(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
{
for (size_t i = 0; i < params.size(); ++i)
return Config::Pairs();
}
+Config::ReturnCode parseReturnCode(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
+{
+ for (size_t i = 0; i < params.size(); ++i)
+ if (params[i].param == paramName)
+ return toReturnCode(params[i].value);
+ return Config::REJECT;
+}
+
bool parseBool(const std::string& paramName, const std::vector<PARAM_VALUE>& params)
{
for (size_t i = 0; i < params.size(); ++i)
if (params[i].param == paramName)
return Config::Section(parseVector("match", params[i].sections),
parseVector("modify", params[i].sections),
- parseVector("reply", params[i].sections));
+ parseVector("reply", params[i].sections),
+ parseReturnCode("no_match", params[i].sections));
return Config::Section();
}
typedef std::map<std::string, std::string> Pairs;
typedef std::pair<std::string, std::string> Pair;
enum Type { UNIX, TCP };
+ enum ReturnCode
+ {
+ REJECT, // Reject the request immediately.
+ FAIL, // Module failed.
+ OK, // Module is OK, continue.
+ HANDLED, // The request is handled, no further handling.
+ INVALID, // The request is invalud.
+ USERLOCK, // Reject the request, user is locked.
+ NOTFOUND, // User not found.
+ NOOP, // Module performed no action.
+ UPDATED // Module sends some updates.
+ };
struct Section
{
Section() {}
- Section(const Pairs& ma, const Pairs& mo, const Pairs& re)
- : match(ma), modify(mo), reply(re) {}
+ Section(const Pairs& ma, const Pairs& mo, const Pairs& re, ReturnCode code)
+ : match(ma), modify(mo), reply(re), returnCode(code) {}
Pairs match;
Pairs modify;
Pairs reply;
+ ReturnCode returnCode;
};
Config() {}
StringGen m_type;
};
+std::string toString(Config::ReturnCode code)
+{
+ switch (code)
+ {
+ case Config::REJECT: return "reject";
+ case Config::FAIL: return "fail";
+ case Config::OK: return "ok";
+ case Config::HANDLED: return "handled";
+ case Config::INVALID: return "invalid";
+ case Config::USERLOCK: return "userlock";
+ case Config::NOTFOUND: return "notfound";
+ case Config::NOOP: return "noop";
+ case Config::UPDATED: return "noop";
+ }
+ return "reject";
+}
+
}
class Conn::Impl
time_t m_lastActivity;
ProtoParser m_parser;
- const Config::Pairs& stagePairs(Config::Pairs Config::Section::* pairs) const
+ template <typename T>
+ const T& stageMember(T Config::Section::* member) const
{
switch (m_parser.stage())
{
- case AUTHORIZE: return m_config.autz.*pairs;
- case AUTHENTICATE: return m_config.auth.*pairs;
- case POSTAUTH: return m_config.postauth.*pairs;
- case PREACCT: return m_config.preacct.*pairs;
- case ACCOUNTING: return m_config.acct.*pairs;
+ case AUTHORIZE: return m_config.autz.*member;
+ case AUTHENTICATE: return m_config.auth.*member;
+ case POSTAUTH: return m_config.postauth.*member;
+ case PREACCT: return m_config.preacct.*member;
+ case ACCOUNTING: return m_config.acct.*member;
}
throw std::runtime_error("Invalid stage: '" + m_parser.stageStr() + "'.");
}
- const Config::Pairs& match() const { return stagePairs(&Config::Section::match); }
- const Config::Pairs& modify() const { return stagePairs(&Config::Section::modify); }
- const Config::Pairs& reply() const { return stagePairs(&Config::Section::reply); }
+ const Config::Pairs& match() const { return stageMember(&Config::Section::match); }
+ const Config::Pairs& modify() const { return stageMember(&Config::Section::modify); }
+ const Config::Pairs& reply() const { return stageMember(&Config::Section::reply); }
+ Config::ReturnCode returnCode() const { return stageMember(&Config::Section::returnCode); }
static void process(void* data);
void processPing();
printfd(__FILE__, "No match. Sending answer...\n");
PacketGen gen("data");
gen.add("result", "no");
+ gen.add("return_code", toString(returnCode()));
m_lastPing = time(NULL);