summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2008-05-03 02:36:31 +0000
committerStef Walter <stef@memberwebs.com>2008-05-03 02:36:31 +0000
commitec0d36ee55709f1df76f977823722a4b53cf27ed (patch)
tree4df12b55e1f5568c85bfc0aec72ae09e219fefa7
parentc6e6d2852303ab491badd3af5571af0f36f67cc5 (diff)
A whole bunch of changes including:
* Measure disk space * Support mulitple IPs per jail.
-rw-r--r--ChangeLog3
-rw-r--r--Makefile.am2
-rw-r--r--common/hash.c24
-rw-r--r--common/hash.h11
-rw-r--r--configure.in2
-rw-r--r--doc/JAILS-MIB.txt14
-rw-r--r--doc/bsnmp-jails.86
-rw-r--r--module/Makefile.am2
-rw-r--r--module/bsnmp-jails.c499
-rw-r--r--module/jails-tree.def4
10 files changed, 501 insertions, 66 deletions
diff --git a/ChangeLog b/ChangeLog
index e3e9b18..cfb7c2e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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)
)
)
)