diff options
author | Stef Walter <stef@memberwebs.com> | 2008-05-03 02:36:31 +0000 |
---|---|---|
committer | Stef Walter <stef@memberwebs.com> | 2008-05-03 02:36:31 +0000 |
commit | ec0d36ee55709f1df76f977823722a4b53cf27ed (patch) | |
tree | 4df12b55e1f5568c85bfc0aec72ae09e219fefa7 | |
parent | c6e6d2852303ab491badd3af5571af0f36f67cc5 (diff) |
A whole bunch of changes including:
* Measure disk space
* Support mulitple IPs per jail.
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | common/hash.c | 24 | ||||
-rw-r--r-- | common/hash.h | 11 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | doc/JAILS-MIB.txt | 14 | ||||
-rw-r--r-- | doc/bsnmp-jails.8 | 6 | ||||
-rw-r--r-- | module/Makefile.am | 2 | ||||
-rw-r--r-- | module/bsnmp-jails.c | 499 | ||||
-rw-r--r-- | module/jails-tree.def | 4 |
10 files changed, 501 insertions, 66 deletions
@@ -2,6 +2,9 @@ - Add tracking of number of processes. - Don't include jails that have no processes (FreeBSD has these when a socket is hung in an open state). + - Add tracking of the amount of disk space and files used by + the jail. + - Support multiple IPs per jail. 0.1 - Initial Release diff --git a/Makefile.am b/Makefile.am index 8352aa0..1c9dd2e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ EXTRA_DIST = common -SUBDIRS = module doc +SUBDIRS = module tools doc dist-hook: rm -rf `find $(distdir)/ -name .svn` diff --git a/common/hash.c b/common/hash.c index 9acd2df..b509d03 100644 --- a/common/hash.c +++ b/common/hash.c @@ -286,6 +286,11 @@ static hsh_entry_t** find_entry(hsh_t* ht, const void* key, size_t klen, const v klen = p - (const unsigned char *)key; } + else if(klen == HSH_KEY_DIRECT) + { + hash = (unsigned int)key; + klen = 0; + } else { for(p = key, i = klen; i; i--, p++) @@ -374,6 +379,25 @@ void* hsh_rem(hsh_t* ht, const void* key, size_t klen) return val; } +void hsh_clear(hsh_t* ht) +{ + hsh_entry_t *he, *next; + int i; + + /* Free all entries in the array */ + for (i = 0; i < ht->max; ++i) { + he = ht->array[i]; + while (he) { + next = he->next; + free (he); + he = next; + } + } + + memset (ht->array, 0, ht->max * sizeof (hsh_entry_t*)); + ht->count = 0; +} + unsigned int hsh_count(hsh_t* ht) { return ht->count; diff --git a/common/hash.h b/common/hash.h index 4dc37b2..bf9d7b8 100644 --- a/common/hash.h +++ b/common/hash.h @@ -134,9 +134,20 @@ hsh_index_t* hsh_next(hsh_index_t* hi); void* hsh_this(hsh_index_t* hi, const void** key, size_t* klen); /* + * hsh_clear: Clear all values from has htable. + */ +void hsh_clear(hsh_t* ht); + +/* * This can be passed as 'klen' in any of the above functions to indicate * a string-valued key, and have hash compute the length automatically. */ #define HSH_KEY_STRING (-1) +/* + * This can be passed as 'klen' in any of the above functions to indicate + * use of the key pointer directly as a hash. + */ +#define HSH_KEY_DIRECT (-2) + #endif /* __HSH_H__ */ diff --git a/configure.in b/configure.in index 27b24a1..ddeaf2a 100644 --- a/configure.in +++ b/configure.in @@ -66,6 +66,6 @@ AC_TYPE_SIZE_T AC_FUNC_MALLOC AC_FUNC_MEMCMP -AC_CONFIG_FILES([Makefile module/Makefile doc/Makefile]) +AC_CONFIG_FILES([Makefile module/Makefile tools/Makefile doc/Makefile]) AC_OUTPUT diff --git a/doc/JAILS-MIB.txt b/doc/JAILS-MIB.txt index f5fa26c..6fac74f 100644 --- a/doc/JAILS-MIB.txt +++ b/doc/JAILS-MIB.txt @@ -122,4 +122,18 @@ jailProcesses OBJECT-TYPE DESCRIPTION "Number of processes running in this jail." ::= { jailEntry 20 } +jailDiskSpace OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Amount of disk space taken by this jail. Zero means unknown." + ::= { jailEntry 30 } + +jailDiskFiles OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Number of files (inodes) in this jail. Zero means unknown." + ::= { jailEntry 31 } + END diff --git a/doc/bsnmp-jails.8 b/doc/bsnmp-jails.8 index 0cd5e07..daaf2db 100644 --- a/doc/bsnmp-jails.8 +++ b/doc/bsnmp-jails.8 @@ -79,9 +79,12 @@ The number of processes running in the jail. .It Ar jails.jailNetworkFilter A tcpdump style filter for the network traffic. Only matched traffic is counted in the jail statistics. -.It Ar jails.jailRefreshRate +.It Ar jails.jailRefreshInterval The interval (in SNMP time ticks) between refreshing the jail process statistics and checking which jails are running. +.It Ar jails.jailMeasureInterval +The interval (in SNMP time ticks) between measuring the amount of +files and disk space used by the jail. .El .Sh OPTIONS To activate the @@ -101,6 +104,7 @@ The following would be added to begemotSnmpdModulePath."jails" = "/usr/local/lib/snmp_jails.so" %jails jailNetworkFilter = "not net 10.0.0.0/8" +jailMeasureInterval = 360000 .Ed .Sh SEE ALSO .Xr bsnmpd 1, diff --git a/module/Makefile.am b/module/Makefile.am index b7e7e15..94a8ee2 100644 --- a/module/Makefile.am +++ b/module/Makefile.am @@ -4,7 +4,7 @@ INCLUDES = -DCONF_PREFIX=\"$(sysconfdir)\" moduledir = $(prefix)/lib module_LTLIBRARIES = snmp_jails.la -snmp_jails_la_CFLAGS = -Wall -I$(top_srcdir) +snmp_jails_la_CFLAGS = -Wall -I$(top_srcdir) -DJAIL_MEASURE_PATH=\""$(libexecdir)/jail-measure"\" snmp_jails_la_LDFLAGS = -module snmp_jails_la_SOURCES = jails_tree.c jails_tree.h jails_oid.h \ bsnmp-jails.c usuals.h ../common/hash.c ../common/hash.h diff --git a/module/bsnmp-jails.c b/module/bsnmp-jails.c index 9e88d5f..87e5136 100644 --- a/module/bsnmp-jails.c +++ b/module/bsnmp-jails.c @@ -49,6 +49,7 @@ #include <sys/sockio.h> #include <sys/sysctl.h> #include <sys/user.h> +#include <sys/wait.h> #include <netinet/in.h> #include <netinet/in_systm.h> @@ -72,6 +73,31 @@ #include "jails_tree.h" #include "jails_oid.h" +/* ------------------------------------------------------------------- + * COMPAT + */ + +struct xprison_v1 { + int pr_version; + int pr_id; + char pr_path[MAXPATHLEN]; + char pr_host[MAXHOSTNAMELEN]; + u_int32_t pr_ip; +}; + +struct xprison_v2 { + int pr_version; + int pr_id; + char pr_path[MAXPATHLEN]; + char pr_host[MAXHOSTNAMELEN]; + u_int32_t pr_ips[JAIL_MAX_IPS]; + u_int pr_nips; +}; + +/* ------------------------------------------------------------------- + * DECLARATIONS + */ + #define SNAP_LEN 48 /* our module handle */ @@ -109,10 +135,13 @@ struct jaildat { int jailid; char *host; char *path; - struct sockaddr_in addr; - /* Network monitor */ - struct monitor *monitor; + /* Monitor pointers for each address */ + char n_addrs; + struct { + struct sockaddr_in ip; + struct monitor *monitor; + } addrs[JAIL_MAX_IPS]; /* Stats gathered */ uint64_t in_octets; @@ -120,6 +149,8 @@ struct jaildat { uint64_t out_octets; uint64_t out_packets; uint32_t n_processes; + uint64_t disk_space; + uint64_t disk_files; }; TAILQ_HEAD(jaildat_list, jaildat); @@ -129,10 +160,14 @@ static struct jaildat_list jaildats = TAILQ_HEAD_INITIALIZER (jaildats); /* number of if jail structures */ static u_int jaildat_count = 0; +static u_int jaildat_index = 0; /* Hash of jail structures by id */ static hsh_t *jaildat_by_host = NULL; +/* Hash of jail structures by path */ +static hsh_t *jaildat_by_path = NULL; + /* Hash of jail structures by address */ static hsh_t *jaildat_by_address = NULL; @@ -142,15 +177,21 @@ static hsh_t *jaildat_by_id = NULL; /* Timer for refreshing the jaildat info */ static void *timer_refresh = NULL; +/* Refresh interval in SNMP ticks */ +static int refresh_interval = 3 * 100; + +/* Timer for measuring the jails */ +static void *timer_measure = NULL; + +/* Measure interval in SNMP ticks */ +static int measure_interval = 1800 * 100; + /* The monitor network filter */ static u_char *network_filter = NULL; /* The KVM interface handle */ static kvm_t *kvm_handle = NULL; -/* Refresh interval in SNMP ticks */ -static int refresh_interval = 300; - /* ----------------------------------------------------------------------------- * HELPERS */ @@ -161,6 +202,7 @@ emsg(const char *format, ...) va_list va; va_start (va, format); vsyslog (LOG_ERR, format, va); + vfprintf (stderr, format, va); va_end (va); } @@ -407,7 +449,7 @@ monitor_create (const char *device) TAILQ_INSERT_TAIL(&monitors, mon, link); mon->device = strdup (device); - mon->handle = pcap_open_live (mon->device, SNAP_LEN, 0, 100, errbuf); + mon->handle = pcap_open_live (mon->device, SNAP_LEN, 1, 100, errbuf); if (!mon->handle) { emsg ("couldn't open monitor on %s: %s", mon->device, errbuf); goto cleanup; @@ -547,6 +589,198 @@ monitor_test_filter (const char *filter) } /* ----------------------------------------------------------------------------- + * MEASURE JAILS + */ + +static void *measure_out_watch = NULL; +static int measure_out_fd = -1; + +static void +measure_parse (char *line) +{ + unsigned long long value; + struct jaildat *jail; + char *p; + + /* Find the first colon */ + p = strchr (line, ':'); + if (!p) { + emsg ("invalid output from measure process: %s", line); + return; + } + + /* Skip past the colon and spaces */ + *p = 0; + ++p; + while (isspace (*p)) + ++p; + + /* Parse the number */ + value = strtoull (p, &p, 10); + + /* Skip past any more spaces */ + while (isspace (*p)) + ++p; + + /* Find a jail with this path */ + jail = hsh_get (jaildat_by_path, p, HSH_KEY_STRING); + if (!jail) + return; + + /* Update the various values */ + if (strcmp (line, "jail-space") == 0) + jail->disk_space = value; + else if (strcmp (line, "jail-files") == 0) + jail->disk_files = value; +} + +static void +measure_io (int fd, void *unused) +{ + char buffer[2048]; + char *line, *next; + int r; + + ASSERT (measure_out_fd == fd); + + r = read (fd, buffer, sizeof (buffer) - 1); + + /* Error conditions */ + if (r < 0) { + if (errno == EAGAIN || errno == EINTR) + return; + emsg ("couldn't read from jail measure: %s", strerror (errno)); + } + + /* Close and disconnect */ + if (r <= 0) { + fd_deselect (measure_out_watch); + measure_out_watch = NULL; + close (measure_out_fd); + measure_out_fd = -1; + return; + } + + /* Null terminate the line */ + ASSERT (r < sizeof (buffer)); + buffer[r] = 0; + line = buffer; + + /* And parse each line received */ + while (line) { + next = strchr (line, '\n'); + if (next) + *(next++) = 0; + while (isspace (*line)) + ++line; + if (*line) + measure_parse (line); + line = next; + } +} + +static char** +measure_get_command (void) +{ + struct jaildat *jail; + char **args; + int i; + + args = calloc (jaildat_count + 4, sizeof (char*)); + if (!args) { + emsg ("out of memory"); + return NULL; + } + + args[0] = JAIL_MEASURE_PATH; + args[1] = "-l"; + args[2] = "11"; /* ie: LOG_ERR | LOG_DAEMON */ + + i = 3; + TAILQ_FOREACH (jail, &jaildats, link) + args[i++] = jail->path; + + return args; +} + +static void +measure_all (void *unused) +{ + char **args; + int pip[2]; + pid_t pid; + int status; + + if (measure_out_watch) { + ASSERT (measure_out_fd != -1); + emsg ("jail measure already in progress, skipping"); + return; + } + + args = measure_get_command (); + if (!args) + return; + + if (pipe (pip) < 0) { + emsg ("couldn't create pipe to do jail measure: %s", strerror (errno)); + free (args); + return; + } + + pid = fork (); + switch (pid) { + case -1: + emsg ("couldn't fork a measure process: %s", strerror (errno)); + free (args); + close (pip[0]); + close (pip[1]); + return; + + case 0: + /* Detach this new process */ + if (daemon (1, 1) < 0) { + emsg ("couldn't daemonize the measure process: %s", strerror (errno)); + exit (1); + } + + /* Dup pipe into stdout for process */ + close (pip[0]); + dup2 (pip[1], 1); + + /* Run the measure process */ + execv (args[0], args); + emsg ("couldn't execute the measure process: %s", strerror (errno)); + exit (1); + break; + + default: + break; + }; + + /* We no longer need this end */ + waitpid (pid, &status, 0); + close (pip[1]); + free (args); + + measure_out_watch = fd_select (pip[0], measure_io, NULL, module); + if (!measure_out_watch) { + emsg ("couldn't watch the measure process output: %s", strerror (errno)); + close (pip[0]); + } + + measure_out_fd = pip[0]; +} + +static void +measure_start (void *unused) +{ + ASSERT (timer_measure); + timer_measure = timer_start_repeat (measure_interval, measure_interval, + measure_all, NULL, module); + measure_all (NULL); +} + +/* ----------------------------------------------------------------------------- * PROCESS LOOKUPS */ @@ -588,6 +822,8 @@ process_refresh_all (void) static void jail_free (struct jaildat *jail) { + int i; + ASSERT (jail); if (jail->jailid) @@ -599,16 +835,21 @@ jail_free (struct jaildat *jail) jail->host = NULL; } - hsh_rem (jaildat_by_address, &(jail->addr), jail->addr.sin_len); + /* Remove all addresses and release monitors */ + for (i = 0; i < jail->n_addrs; ++i) { + hsh_rem (jaildat_by_address, &(jail->addrs[i].ip), + jail->addrs[i].ip.sin_len); + if (jail->addrs[i].monitor) + monitor_unref (jail->addrs[i].monitor); + memset (&jail->addrs[i], 0, sizeof (jail->addrs[i])); + } - if (jail->path) + if (jail->path) { + hsh_rem (jaildat_by_path, jail->path, HSH_KEY_STRING); free (jail->path); + } jail->path = NULL; - if (jail->monitor) - monitor_unref (jail->monitor); - jail->monitor = NULL; - if (jail->index) { TAILQ_REMOVE (&jaildats, jail, link); jaildat_count--; @@ -619,19 +860,23 @@ jail_free (struct jaildat *jail) static int jail_update (struct jaildat *jail, int jailid, const char *host, - const char *path, struct in_addr *addr) + const char *path, u_int32_t *ips, u_int n_ips) { - struct monitor *mon; + struct monitor *mon = NULL; + struct sockaddr_in addr; char *dup; + int i, top; ASSERT (jail); + /* Do the jail id */ if (jail->jailid != jailid) { hsh_rem (jaildat_by_id, &jail->jailid, sizeof (jail->jailid)); jail->jailid = jailid; hsh_set (jaildat_by_id, &jail->jailid, sizeof (jail->jailid), jail); } + /* Do the host */ if (!host) host = ""; @@ -647,40 +892,78 @@ jail_update (struct jaildat *jail, int jailid, const char *host, hsh_set (jaildat_by_host, jail->host, HSH_KEY_STRING, jail); } + /* Do the path */ if (!path) path = ""; + if (!jail->path || strcmp (jail->path, path) != 0) { dup = strdup (path); if (!dup) return -1; - if (jail->path) + if (jail->path) { + hsh_rem (jaildat_by_path, jail->path, HSH_KEY_STRING); free (jail->path); + } jail->path = dup; + hsh_set (jaildat_by_path, jail->path, HSH_KEY_STRING, jail); } - if (memcmp (&jail->addr.sin_addr, addr, sizeof (jail->addr.sin_addr)) != 0) { - if (jail->addr.sin_len) - hsh_rem (jaildat_by_address, &(jail->addr), jail->addr.sin_len); - jail->addr.sin_family = AF_INET; - jail->addr.sin_len = sizeof (jail->addr); - jail->addr.sin_port = 0; - memcpy (&jail->addr.sin_addr, addr, sizeof (jail->addr.sin_addr)); - hsh_set (jaildat_by_address, &(jail->addr), jail->addr.sin_len, jail); - - mon = monitor_for_address ((struct sockaddr*)&jail->addr); - if (mon && mon != jail->monitor) { - monitor_ref (mon); - if (jail->monitor) - monitor_unref (jail->monitor); - jail->monitor = mon; + /* Do the addresses */ + top = (jail->n_addrs > n_ips ? jail->n_addrs : n_ips); + for (i = 0; i < top; ++i) { + + /* Setup the address */ + if (i < n_ips) { + memset (&addr, 0, sizeof (addr)); + addr.sin_family = AF_INET; + addr.sin_len = sizeof (addr); + addr.sin_port = 0; + addr.sin_addr.s_addr = ntohl (ips[i]); + + /* Same? skip. */ + if (i < jail->n_addrs && + memcmp (&jail->addrs[i].ip, &addr, sizeof (addr)) == 0) + continue; + } + + /* Remove old address */ + if (i < jail->n_addrs) { + hsh_rem (jaildat_by_address, &(jail->addrs[i].ip), + jail->addrs[i].ip.sin_len); + memset (&jail->addrs[i].ip, 0, sizeof (jail->addrs[i].ip)); + } + + /* Add new address */ + if (i < n_ips) { + memcpy (&jail->addrs[i].ip, &addr, sizeof (addr)); + hsh_set (jaildat_by_address, &(jail->addrs[i].ip), + jail->addrs[i].ip.sin_len, jail); + } + + /* Register new monitor */ + mon = NULL; + if (i < n_ips) { + mon = monitor_for_address ((struct sockaddr*)&addr); + if (mon) + monitor_ref (mon); } + + /* Free the old monitor */ + if (i < jail->n_addrs && jail->addrs[i].monitor) + monitor_unref (jail->addrs[i].monitor); + + /* Assign the monitor */ + jail->addrs[i].monitor = mon; } + jail->n_addrs = n_ips; + return 0; } static struct jaildat* -jail_alloc (int jailid, const char *host, const char *path, struct in_addr *addr) +jail_alloc (int jailid, const char *host, const char *path, + u_int32_t *ips, u_int n_ips) { struct jaildat *jail; @@ -688,25 +971,85 @@ jail_alloc (int jailid, const char *host, const char *path, struct in_addr *addr if (!jail) return NULL; - if (jail_update (jail, jailid, host, path, addr) < 0) { + if (jail_update (jail, jailid, host, path, ips, n_ips) < 0) { jail_free (jail); return NULL; } jaildat_count++; - jail->index = jaildat_count; + jail->index = ++jaildat_index; INSERT_OBJECT_INT (jail, &jaildats); return jail; } static void +jail_refresh_v1 (struct xprison_v1 *xp, size_t len) +{ + struct jaildat *jail; + int i; + + /* Make sure its kosher */ + if (len < sizeof (*xp) || len % sizeof (*xp)) { + emsg ("not a valid v1 xprison. kernel and userland out of sync?"); + return; + } + + /* + * Allocate new jails, and update old ones. We iterate backwards + * so that if there are multiple jails with the same host name + * (some possibly zombies), then we'll see the most recent one. + */ + for (i = (len / sizeof (*xp)) - 1; i >= 0; --i) { + jail = hsh_get (jaildat_by_host, xp[i].pr_host, HSH_KEY_STRING); + if (!jail) + jail = jail_alloc (xp[i].pr_id, xp[i].pr_host, xp[i].pr_path, + &xp[i].pr_ip, 1); + else + jail_update (jail, xp[i].pr_id, xp[i].pr_host, xp[i].pr_path, + &xp[i].pr_ip, 1); + if (jail) + jail->mark = 0; + } +} + +static void +jail_refresh_v2 (struct xprison_v2 *xp, size_t len) +{ + struct jaildat *jail; + int i; + + /* Make sure its kosher */ + if (len < sizeof (*xp) || len % sizeof (*xp)) { + emsg ("not a valid v2 xprison. kernel and userland out of sync?"); + return; + } + + /* + * Allocate new jails, and update old ones. We iterate backwards + * so that if there are multiple jails with the same host name + * (some possibly zombies), then we'll see the most recent one. + */ + for (i = (len / sizeof (*xp)) - 1; i >= 0; --i) { + jail = hsh_get (jaildat_by_host, xp[i].pr_host, HSH_KEY_STRING); + if (!jail) + jail = jail_alloc (xp[i].pr_id, xp[i].pr_host, xp[i].pr_path, + xp[i].pr_ips, xp[i].pr_nips); + else + jail_update (jail, xp[i].pr_id, xp[i].pr_host, xp[i].pr_path, + xp[i].pr_ips, xp[i].pr_nips); + if (jail) + jail->mark = 0; + } +} + +static void jail_refresh_all (void* unused) { - struct xprison *sxp, *xp; - struct in_addr in; + struct xprison *sxp = NULL; struct jaildat *jail, *tmp; - size_t i, len; + size_t len; + int i; /* Get the length of the list */ if (sysctlbyname ("security.jail.list", NULL, &len, NULL, 0) == -1) { @@ -717,14 +1060,15 @@ jail_refresh_all (void* unused) /* Retrieve actual data */ for (i = 0; i < 4; i++) { if (len <= 0) - return; - sxp = xp = malloc (len); + break; + + sxp = malloc (len); if (sxp == NULL) { emsg ("out of memory"); return; } - if (sysctlbyname ("security.jail.list", xp, &len, NULL, 0) == -1) { + if (sysctlbyname ("security.jail.list", sxp, &len, NULL, 0) == -1) { free (sxp); sxp = NULL; if (errno == ENOMEM) @@ -739,28 +1083,19 @@ jail_refresh_all (void* unused) break; } - /* Make sure its kosher */ - if (len < sizeof (*xp) || len % sizeof (*xp) || xp->pr_version != XPRISON_VERSION) { - emsg ("kernel and userland out of sync"); - free (sxp); - return; - } - /* Mark and prepare for sweep below */ TAILQ_FOREACH (jail, &jaildats, link) jail->mark = 1; - /* Allocate new jails, and update old ones */ - for (i = 0; i < len / sizeof (*xp); ++i) { - in.s_addr = ntohl (xp->pr_ip); - jail = hsh_get (jaildat_by_host, xp->pr_host, HSH_KEY_STRING); - if (!jail) - jail = jail_alloc (xp->pr_id, xp->pr_host, xp->pr_path, &in); + if (len > 0) { + if (sxp->pr_version == 1) + jail_refresh_v1 ((struct xprison_v1*)sxp, len); + else if (sxp->pr_version == 2) + jail_refresh_v2 ((struct xprison_v2*)sxp, len); else - jail_update (jail, xp->pr_id, xp->pr_host, xp->pr_path, &in); + emsg ("unsupported kernel structure version: %d\n", sxp->pr_version); - jail->mark = 0; - xp++; + free (sxp); } /* Sweep any jails that are no longer */ @@ -769,8 +1104,6 @@ jail_refresh_all (void* unused) jail_free (jail); } - free (sxp); - process_refresh_all (); /* Remove any jails that have no processes (kernel anomally) */ @@ -798,6 +1131,9 @@ op_jailconfig (struct snmp_context *ctx, struct snmp_value *value, case LEAF_jailRefreshInterval: value->v.uint32 = refresh_interval; return SNMP_ERR_NOERROR; + case LEAF_jailMeasureInterval: + value->v.uint32 = measure_interval; + return SNMP_ERR_NOERROR; default: ASSERT (0); return -1; @@ -848,6 +1184,22 @@ op_jailconfig (struct snmp_context *ctx, struct snmp_value *value, }; break; + case LEAF_jailMeasureInterval: + switch (op) { + case SNMP_OP_SET: + ctx->scratch->int1 = measure_interval; + measure_interval = value->v.uint32; + return SNMP_ERR_NOERROR; + case SNMP_OP_ROLLBACK: + measure_interval = ctx->scratch->int1; + return SNMP_ERR_NOERROR; + case SNMP_OP_COMMIT: + return SNMP_ERR_NOERROR; + default: + ASSERT (0); + return SNMP_ERR_GENERR; + }; + break; default: ASSERT (0); return SNMP_ERR_GENERR; @@ -893,20 +1245,26 @@ op_jailentry (struct snmp_context *ctx, struct snmp_value *value, case LEAF_jailHost: return string_get (value, jail->host, -1); case LEAF_jailInOctets: - value->v.uint32 = jail->in_octets; + value->v.counter64 = jail->in_octets; return SNMP_ERR_NOERROR; case LEAF_jailInPackets: - value->v.uint32 = jail->in_packets; + value->v.counter64 = jail->in_packets; return SNMP_ERR_NOERROR; case LEAF_jailOutOctets: - value->v.uint32 = jail->out_octets; + value->v.counter64 = jail->out_octets; return SNMP_ERR_NOERROR; case LEAF_jailOutPackets: - value->v.uint32 = jail->out_packets; + value->v.counter64 = jail->out_packets; return SNMP_ERR_NOERROR; case LEAF_jailProcesses: value->v.integer = jail->n_processes; return SNMP_ERR_NOERROR; + case LEAF_jailDiskSpace: + value->v.counter64 = jail->disk_space; + return SNMP_ERR_NOERROR; + case LEAF_jailDiskFiles: + value->v.counter64 = jail->disk_files; + return SNMP_ERR_NOERROR; default: ASSERT (0); return SNMP_ERR_NOSUCHNAME; @@ -982,6 +1340,10 @@ module_fini (void) hsh_free (jaildat_by_host); jaildat_by_host = NULL; + if (jaildat_by_path) + hsh_free (jaildat_by_path); + jaildat_by_path = NULL; + while ((jail = TAILQ_FIRST(&jaildats)) != NULL) jail_free (jail); @@ -992,6 +1354,10 @@ module_fini (void) timer_stop (timer_refresh); timer_refresh = NULL; + if (timer_measure) + timer_stop (timer_measure); + timer_measure = NULL; + return 0; } @@ -1031,6 +1397,10 @@ module_init (struct lmodule *mod, int argc, char *argv[]) if (!jaildat_by_host) goto cleanup; + jaildat_by_path = hsh_create (); + if (!jaildat_by_path) + goto cleanup; + jaildat_by_address = hsh_create (); if (!jaildat_by_address) goto cleanup; @@ -1059,6 +1429,11 @@ module_start (void) jail_refresh_all, NULL, module); if (!timer_refresh) emsg ("couldn't setup timer to refresh jails"); + + /* Wait for some time before first measure */ + timer_measure = timer_start (measure_interval / 5, measure_start, NULL, module); + if (!timer_measure) + emsg ("couldn't setup timer to measure jails"); } const struct snmp_module config = { diff --git a/module/jails-tree.def b/module/jails-tree.def index 6d5a79a..2efcb4a 100644 --- a/module/jails-tree.def +++ b/module/jails-tree.def @@ -53,12 +53,16 @@ (13 jailOutPackets COUNTER64 GET) (20 jailProcesses INTEGER GET) + + (30 jailDiskSpace COUNTER64 GET) + (31 jailDiskFiles COUNTER64 GET) ) ) # Valid only during configuration (100 jailNetworkFilter OCTETSTRING op_jailconfig GET SET) (101 jailRefreshInterval TIMETICKS op_jailconfig GET SET) + (102 jailMeasureInterval TIMETICKS op_jailconfig GET SET) ) ) ) |