X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=hostinfod%2Fcommands.c;h=8fd22463cb8f4fa1edcb2af05cc9ce4f10e9dc41;hb=e43e15284e3c91f9cdc2ba1e48b81f2c5ebe36fc;hp=b928c36d5c1531880370ce12c87e1614d3b3453e;hpb=bfa3107b71951961644d5ddc4f0ff3e54abd0700;p=virt-hostinfo.git diff --git a/hostinfod/commands.c b/hostinfod/commands.c index b928c36..8fd2246 100644 --- a/hostinfod/commands.c +++ b/hostinfod/commands.c @@ -32,13 +32,16 @@ #include #include #include +#include #include #include #include +#include #include #include "hostinfod.h" +#include "apr12-compat.h" #define PROTOCOL_VERSION "1.0" #define CRLF "\r\n" @@ -61,6 +64,9 @@ execute_command (const struct timespec *now, apr_array_header_t *args; struct arg arg; command_fn fn; + int enabled; + double interval; + struct timespec *last; debug ("%s: %s", hval->name, command); @@ -84,7 +90,7 @@ execute_command (const struct timespec *now, */ len = strlen (command); if (len < 1 || len > 4094 || not_printable (command)) { - warning ("%s: command too short, too long or contained unprintable chars (len = %d)", + warning ("%s: command too short, too long or contained unprintable chars (len = %zu)", hval->name, len); send_error (hval, 400); return; @@ -169,7 +175,7 @@ execute_command (const struct timespec *now, default: unknown_arg: - warning ("%s: unknown or malformed argument starting at position %d ('%c')", + warning ("%s: unknown or malformed argument starting at position %zu ('%c')", hval->name, i, command[i]); send_error (hval, 400); return; @@ -187,11 +193,11 @@ execute_command (const struct timespec *now, switch (arg.type) { case arg_type_bool: case arg_type_int: - debug ("%s: arg %d : %s = %ld", + debug ("%s: arg %zu : %s = %ld", hval->name, i, string_of_arg_type (arg.type), arg.u.i); break; case arg_type_string: - debug ("%s: arg %d : %s = %s", + debug ("%s: arg %zu : %s = %s", hval->name, i, string_of_arg_type (arg.type), arg.u.str); break; } @@ -208,8 +214,42 @@ execute_command (const struct timespec *now, /* Before dispatching the command, check the command is enabled * and guest is not calling it too frequently. */ - error ("XXXXXXX enabled check not implemented XXXXXXX"); - error ("XXXXXXX frequency check not implemented XXXXXXX"); + check_guests_file (hval, cmd, &interval, &enabled); + + if (!enabled) { + warning ("%s: guest tried disabled command '%s'", hval->name, cmd); + send_error (hval, 401); + return; + } + + last = apr_hash_get (hval->lasttime, cmd, APR_HASH_KEY_STRING); + if (last) { + struct timespec timediff; + double interval_int, interval_frac; + struct timespec interval_ts; + + diff_timespec (&timediff, now, last); + + interval_frac = modf (interval, &interval_int); + interval_ts.tv_sec = interval_int; + interval_ts.tv_nsec = interval_frac * 1000000000; + + debug ("%s: %s: interval %ds %ldns, time since last %ds %ldns", + hval->name, cmd, + (int) interval_ts.tv_sec, interval_ts.tv_nsec, + (int) timediff.tv_sec, timediff.tv_nsec); + + if (interval_ts.tv_sec > timediff.tv_sec || + (interval_ts.tv_sec == timediff.tv_sec && + interval_ts.tv_nsec > timediff.tv_nsec)) { + warning ("%s: command '%s' exceeded interval allowed", hval->name, cmd); + send_error (hval, 406); + return; + } + } + + last = apr_pmemdup (hval->pool, now, sizeof *now); + apr_hash_set (hval->lasttime, cmd, APR_HASH_KEY_STRING, last); /* Dispatch the command. */ fn (hval, cmd, args);