diff options
| -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)            )          )        )  | 
