0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-20 04:02:15 +02:00

Log unused options, i.e. options specified in config file that were

unrecognized, ignored, or unused.

This behavior is somewhat different (by design) to 2.x branch, which
will raise a fatal exception if an unrecognized option is
encountered.
This commit is contained in:
James Yonan 2013-06-10 00:42:19 +00:00
parent 906584ba3b
commit cf39be0516
9 changed files with 131 additions and 27 deletions

View File

@ -336,7 +336,7 @@ namespace openvpn {
const ParseClientConfig cc = ParseClientConfig::parse(config.content, &kvl, options);
#ifdef OPENVPN_DUMP_CONFIG
std::cout << "---------- ARGS ----------" << std::endl;
std::cout << options.render() << std::endl;
std::cout << options.render(Option::RENDER_PASS_FMT|Option::RENDER_NUMBER|Option::RENDER_BRACKET) << std::endl;
std::cout << "---------- MAP ----------" << std::endl;
std::cout << options.render_map() << std::endl;
#endif

View File

@ -314,6 +314,10 @@ namespace openvpn {
push_base->singleton.extend(opt, "redirect-dns");
push_base->singleton.extend(opt, "inactive");
}
// show unused options
if (opt.n_unused())
OPENVPN_LOG("UNUSED OPTIONS" << std::endl << opt.render(Option::RENDER_TRUNC_64|Option::RENDER_NUMBER|Option::RENDER_BRACKET|Option::RENDER_UNUSED));
}
void next()

View File

@ -424,7 +424,7 @@ namespace openvpn {
if (received_options.complete())
{
// show options
OPENVPN_LOG("OPTIONS:" << std::endl << render_options_sanitized(received_options));
OPENVPN_LOG("OPTIONS:" << std::endl << render_options_sanitized(received_options, Option::RENDER_PASS_FMT|Option::RENDER_NUMBER|Option::RENDER_BRACKET));
// process auth-token
extract_auth_token(received_options);

View File

@ -24,7 +24,7 @@ namespace openvpn {
{
const bool ret = filt(opt);
if (!ret)
OPENVPN_LOG("Ignored due to route-nopull: " << opt.render());
OPENVPN_LOG("Ignored due to route-nopull: " << opt.render(Option::RENDER_TRUNC_64|Option::RENDER_BRACKET));
return ret;
}

View File

@ -368,6 +368,7 @@ namespace openvpn {
{
try {
const Option& o = opt[*i];
o.touch();
const std::string& conn_block_text = o.get(1, Option::MULTILINE);
OptionList::Limits limits("<connection> block is too large",
max_conn_block_size,
@ -684,6 +685,7 @@ namespace openvpn {
{
Item::Ptr e(new Item());
const Option& o = opt[*i];
o.touch();
e->server_host = o.get(1, 256);
if (o.size() >= 3)
{

View File

@ -71,6 +71,17 @@ namespace openvpn {
STATUS_LENGTH,
};
// Options for render methods
enum render_flags {
RENDER_TRUNC_64 = (1<<0), // truncate option after 64 chars
RENDER_PASS_FMT = (1<<1), // pass \r\n\t
RENDER_NUMBER = (1<<2), // number lines
RENDER_BRACKET = (1<<3), // quote options using []
RENDER_UNUSED = (1<<4), // only show unused options
};
Option() : touched_(false) {}
static validate_status validate(const std::string& str, const size_t max_len)
{
const size_t pos = str.find_first_of("\r\n");
@ -162,11 +173,20 @@ namespace openvpn {
return NULL;
}
std::string render() const
std::string render(const unsigned int flags) const
{
std::ostringstream out;
size_t max_len_flags = (flags & RENDER_TRUNC_64) ? 64 : 0;
if (flags & RENDER_PASS_FMT)
max_len_flags |= Unicode::UTF8_PASS_FMT;
for (std::vector<std::string>::const_iterator i = data.begin(); i != data.end(); ++i)
out << '[' << Unicode::utf8_printable(*i, 0 | Unicode::UTF8_PASS_FMT) << "] ";
{
if (flags & RENDER_BRACKET)
out << '[';
out << Unicode::utf8_printable(*i, max_len_flags);
if (flags & RENDER_BRACKET)
out << "] ";
}
return out.str();
}
@ -193,6 +213,18 @@ namespace openvpn {
data.erase(data.begin(), data.begin() + n);
}
// indicate that this option was processed
void touch() const
{
// Note that we violate constness here, which is done
// because the touched bit is considered to be option metadata.
Option *self = const_cast<Option *>(this);
self->touched_ = true;
}
// was this option processed?
bool touched() const { return touched_; }
private:
std::string err_ref() const
{
@ -206,6 +238,7 @@ namespace openvpn {
return ret;
}
bool touched_;
std::vector<std::string> data;
};
@ -706,7 +739,10 @@ namespace openvpn {
{
const Option& opt = *i;
if (!filt || filt->filter(opt))
push_back(opt);
{
push_back(opt);
opt.touch();
}
}
}
@ -717,7 +753,11 @@ namespace openvpn {
IndexMap::const_iterator oi = other.map().find(name);
if (oi != other.map().end())
for (IndexList::const_iterator i = oi->second.begin(); i != oi->second.end(); ++i)
push_back(other[*i]);
{
const Option& opt = other[*i];
push_back(opt);
opt.touch();
}
}
// Append to self only those elements in other that do not exist
@ -730,7 +770,10 @@ namespace openvpn {
{
const Option& opt = *i;
if (!opt.empty() && map().find(opt.ref(0)) == map().end())
push_back(opt);
{
push_back(opt);
opt.touch();
}
}
}
@ -743,7 +786,11 @@ namespace openvpn {
{
const size_t size = e->second.size();
if (size)
return &((*this)[e->second[size-1]]);
{
const Option* ret = &((*this)[e->second[size-1]]);
ret->touch();
return ret;
}
}
return NULL;
}
@ -756,7 +803,11 @@ namespace openvpn {
if (e != map_.end() && !e->second.empty())
{
if (e->second.size() == 1)
return &((*this)[e->second[0]]);
{
const Option* ret = &((*this)[e->second[0]]);
ret->touch();
return ret;
}
else
OPENVPN_THROW(option_error, "more than one instance of option '" << name << '\'');
}
@ -772,11 +823,16 @@ namespace openvpn {
if (e != map_.end() && !e->second.empty())
{
const Option *first = &((*this)[e->second[0]]);
first->touch();
if (e->second.size() >= 2)
{
for (size_t i = 1; i < e->second.size(); ++i)
if (((*this)[e->second[i]]) != *first)
OPENVPN_THROW(option_error, "more than one instance of option '" << name << "' with inconsistent argument(s)");
{
const Option *other = &(*this)[e->second[i]];
other->touch();
if (*other != *first)
OPENVPN_THROW(option_error, "more than one instance of option '" << name << "' with inconsistent argument(s)");
}
}
return first;
}
@ -841,6 +897,7 @@ namespace openvpn {
const Option& o = (*this)[*i];
if (o.size() >= 2)
{
o.touch();
ret += o.ref(1);
string::add_trailing_in_place(ret, '\n');
}
@ -853,15 +910,13 @@ namespace openvpn {
// instances of the option exist.
bool exists_unique(const std::string& name) const
{
const Option* o = get_unique_ptr(name);
return o != NULL;
return get_unique_ptr(name) != NULL;
}
// Return true if one or more instances of a given option exist.
bool exists(const std::string& name) const
{
const OptionList::IndexList* il = get_index_ptr(name);
return il != NULL;
return get_ptr(name) != NULL;
}
// Convenience method that gets a particular argument index within an option,
@ -885,14 +940,34 @@ namespace openvpn {
return "";
}
std::string render() const
// Touch an option, if it exists.
void touch(const std::string& name) const
{
const Option* o = get_ptr(name);
if (o)
o->touch();
}
// Render object as a string.
// flags should be given as Option::render_flags.
std::string render(const unsigned int flags) const
{
std::ostringstream out;
for (size_t i = 0; i < size(); ++i)
out << i << ' ' << (*this)[i].render() << std::endl;
{
const Option& o = (*this)[i];
if (!(flags & Option::RENDER_UNUSED) || !o.touched())
{
if (flags & Option::RENDER_NUMBER)
out << i << ' ';
out << o.render(flags) << std::endl;
}
}
return out.str();
}
// Render contents of hash map used to locate options after underlying option list
// has been modified.
std::string render_map() const
{
std::ostringstream out;
@ -906,7 +981,22 @@ namespace openvpn {
return out.str();
}
void add_item(const Option& opt) // updates map as well
// Return number of unused options based on the notion that
// all used options have been touched.
size_t n_unused() const
{
size_t n = 0;
for (std::vector<Option>::const_iterator i = begin(); i != end(); ++i)
{
const Option& opt = *i;
if (!opt.touched())
++n;
}
return n;
}
// Add item to underlying option list while updating map as well.
void add_item(const Option& opt)
{
if (!opt.empty())
{
@ -916,8 +1006,11 @@ namespace openvpn {
}
}
// Return hash map used to locate options.
const IndexMap& map() const { return map_; }
// Rebuild hash map used to locate options after underlying option list
// has been modified.
void update_map()
{
map_.clear();

View File

@ -72,7 +72,7 @@ namespace openvpn {
}
catch (const std::exception& e)
{
OPENVPN_THROW(route_error, "error parsing received route: " << o.render() << " : " << e.what());
OPENVPN_THROW(route_error, "error parsing received route: " << o.render(Option::RENDER_TRUNC_64|Option::RENDER_BRACKET) << " : " << e.what());
}
}
}

View File

@ -18,7 +18,7 @@
namespace openvpn {
inline std::string render_options_sanitized(const OptionList& opt)
inline std::string render_options_sanitized(const OptionList& opt, const unsigned int render_flags)
{
std::ostringstream out;
for (size_t i = 0; i < opt.size(); i++)
@ -29,7 +29,7 @@ namespace openvpn {
out << i << " [auth-token] ..." << std::endl;
else
#endif
out << i << ' ' << o.render() << std::endl;
out << i << ' ' << o.render(render_flags) << std::endl;
}
return out.str();
}

View File

@ -193,6 +193,11 @@ namespace openvpn {
F_ADD_DNS=(1<<0),
};
// render option flags
enum {
OPT_RENDER_FLAGS = Option::RENDER_TRUNC_64 | Option::RENDER_BRACKET
};
public:
virtual void client_start(const OptionList& opt, TransportClient& transcli)
{
@ -590,7 +595,7 @@ namespace openvpn {
catch (const std::exception& e)
{
if (!quiet)
OPENVPN_LOG("Error parsing IPv4 route: " << o.render() << " : " << e.what());
OPENVPN_LOG("Error parsing IPv4 route: " << o.render(OPT_RENDER_FLAGS) << " : " << e.what());
}
}
}
@ -618,7 +623,7 @@ namespace openvpn {
catch (const std::exception& e)
{
if (!quiet)
OPENVPN_LOG("Error parsing IPv6 route: " << o.render() << " : " << e.what());
OPENVPN_LOG("Error parsing IPv6 route: " << o.render(OPT_RENDER_FLAGS) << " : " << e.what());
}
}
}
@ -707,12 +712,12 @@ namespace openvpn {
validate_port(o.get(3, 256), "PROXY_HTTPS port", &https_port);
}
else if (!quiet)
OPENVPN_LOG("Unknown pushed DHCP option: " << o.render());
OPENVPN_LOG("Unknown pushed DHCP option: " << o.render(OPT_RENDER_FLAGS));
}
catch (const std::exception& e)
{
if (!quiet)
OPENVPN_LOG("Error parsing dhcp-option: " << o.render() << " : " << e.what());
OPENVPN_LOG("Error parsing dhcp-option: " << o.render(OPT_RENDER_FLAGS) << " : " << e.what());
}
}
try {
@ -757,7 +762,7 @@ namespace openvpn {
catch (const std::exception& e)
{
if (!quiet)
OPENVPN_LOG("Error parsing dhcp-option: " << o.render() << " : " << e.what());
OPENVPN_LOG("Error parsing dhcp-option: " << o.render(OPT_RENDER_FLAGS) << " : " << e.what());
}
}
}