diff options
Diffstat (limited to 'module')
-rw-r--r-- | module/Makefile.am | 19 | ||||
-rw-r--r-- | module/bsnmp-jails.c | 947 | ||||
-rw-r--r-- | module/jails-tree.def | 64 | ||||
-rw-r--r-- | module/usuals.h | 68 |
4 files changed, 1098 insertions, 0 deletions
diff --git a/module/Makefile.am b/module/Makefile.am new file mode 100644 index 0000000..b7e7e15 --- /dev/null +++ b/module/Makefile.am @@ -0,0 +1,19 @@ + +INCLUDES = -DCONF_PREFIX=\"$(sysconfdir)\" + +moduledir = $(prefix)/lib +module_LTLIBRARIES = snmp_jails.la + +snmp_jails_la_CFLAGS = -Wall -I$(top_srcdir) +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 + +jails_tree.c: jails-tree.def + gensnmptree -e jails > jails_oid.h < $(srcdir)/jails-tree.def + gensnmptree -p jails_ < $(srcdir)/jails-tree.def + +EXTRA_DIST = jails-tree.def + +CLEANFILES = jails_tree.* \ + jails_oid.h diff --git a/module/bsnmp-jails.c b/module/bsnmp-jails.c new file mode 100644 index 0000000..f08da30 --- /dev/null +++ b/module/bsnmp-jails.c @@ -0,0 +1,947 @@ +/* + * Copyright (c) 2008, Stefan Walter + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * + * CONTRIBUTORS + * Stefan Walter <stef@memberwebs.com> + */ + +#include "usuals.h" + +#include <sys/param.h> +#include <sys/types.h> + +#include <sys/jail.h> +#include <sys/limits.h> +#include <sys/queue.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <sys/sockio.h> +#include <sys/sysctl.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <arpa/inet.h> + +#include <syslog.h> +#include <unistd.h> +#include <stdarg.h> +#include <ctype.h> +#include <fcntl.h> + +#include <bsnmp/snmpmod.h> +#include <pcap.h> + +#include "common/hash.h" + +#include "jails_tree.h" +#include "jails_oid.h" + +#define SNAP_LEN 48 + +/* our module handle */ +static struct lmodule *module; + +/* OIDs */ +static const struct asn_oid oid_jails = OIDX_jails; + +/* the Object Resource registration index */ +static u_int reg_index = 0; + +struct monitor { + TAILQ_ENTRY(monitor) link; + + int refs; + + char *device; + pcap_t *handle; + void *watch; + struct bpf_program filter; + int filter_valid; +}; + +TAILQ_HEAD(monitor_list, monitor); + +/* list of monitor structures */ +static struct monitor_list monitors = TAILQ_HEAD_INITIALIZER (monitors); + +struct jaildat { + uint32_t index; + TAILQ_ENTRY(jaildat) link; + int mark; + + /* Configuration */ + char *host; + char *path; + struct sockaddr_in addr; + + /* Network monitor */ + struct monitor *monitor; + + /* Stats gathered */ + uint64_t in_octets; + uint64_t in_packets; + uint64_t out_octets; + uint64_t out_packets; +}; + +TAILQ_HEAD(jaildat_list, jaildat); + +/* list of jail structures */ +static struct jaildat_list jaildats = TAILQ_HEAD_INITIALIZER (jaildats); + +/* number of if jail structures */ +static u_int jaildat_count = 0; + +/* Hash of jail structures by id */ +static hsh_t *jaildat_by_host = NULL; + +/* Hash of jail structures by address */ +static hsh_t *jaildat_by_address = NULL; + +/* Timer for refreshing the jaildat info */ +static void *timer_refresh = NULL; + +/* The monitor network filter */ +static u_char *network_filter = NULL; + + +/* ----------------------------------------------------------------------------- + * HELPERS + */ + +static void +emsg(const char *format, ...) +{ + va_list va; + va_start (va, format); + vsyslog (LOG_ERR, format, va); + va_end (va); +} + +typedef void* (*if_enumerator) (struct ifreq *ifr, void* data); + +static void* +enumerate_ifs (if_enumerator func, void* data) +{ + int sockfd = -1; + struct ifconf ifc; + struct ifreq *ifr = NULL; + unsigned char *ptr; + unsigned char *buf = NULL; + void *result = NULL; + + ASSERT (func); + + ifc.ifc_len = 32768; + buf = malloc (ifc.ifc_len); + ifc.ifc_req = (struct ifreq*)buf; + if (!buf) { + emsg ("couldn't allocate buffer to list interfaces: out of memory"); + goto cleanup; + } + + sockfd = socket (AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) { + emsg ("couldn't create socket to list interfaces: %s", strerror (errno)); + goto cleanup; + } + + if (ioctl (sockfd, SIOCGIFCONF, &ifc) < 0) { + emsg ("couldn't list interfaces: %s", strerror (errno)); + goto cleanup; + } + + #define IFR_SIZE(ifr) \ + (max ((ifr)->ifr_addr.sa_len, sizeof((ifr)->ifr_addr)) + sizeof((ifr)->ifr_name)) + + for (ptr = buf; ptr < buf + ifc.ifc_len; ) { + ifr = (struct ifreq*)ptr; + ptr += IFR_SIZE (ifr); + + result = (func) (ifr, data); + if (result) + break; + } + +cleanup: + if (sockfd >= 0) + close (sockfd); + if (buf) + free (buf); + return result; +} + +/* ----------------------------------------------------------------------------- + * MONITORING + */ + +#pragma pack(1) + +/* Ethernet header */ +struct ethhdr { + #define ETHER_ADDR_LEN 6 + u_char dhost[ETHER_ADDR_LEN]; /* Destination host address */ + u_char shost[ETHER_ADDR_LEN]; /* Source host address */ + u_short type; /* IP? ARP? RARP? etc */ +}; + +/* IP4 header */ +struct ip4hdr { + uint8_t vhl; /* version << 4 | header length >> 2 */ + uint8_t tos; /* type of service */ + uint16_t len; /* total length */ + uint16_t id; /* identification */ + uint16_t off; /* fragment offset field */ + #define IP_RF 0x8000 /* reserved fragment flag */ + #define IP_DF 0x4000 /* dont fragment flag */ + #define IP_MF 0x2000 /* more fragments flag */ + #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + uint8_t ttl; /* time to live */ + uint8_t proto; /* protocol */ + uint16_t sum; /* checksum */ + struct in_addr src, dst; /* source and dest address */ +}; + +/* IP6 header */ +struct ip6hdr { + int32_t flow; + int16_t payload; + int8_t next; + int8_t hops; + struct in6_addr src, dst; +}; + +#pragma pack() + +static void +process_ip4 (const struct ip4hdr *hdr, uint32_t octets) +{ + struct sockaddr_in addr; + struct jaildat *jail; + + ASSERT (hdr); + + /* Try incoming */ + memset (&addr, 0, sizeof (addr)); + addr.sin_family = AF_INET; + addr.sin_len = sizeof (addr); + addr.sin_port = 0; + memcpy (&addr.sin_addr, &hdr->dst, sizeof (addr.sin_addr)); + + jail = hsh_get (jaildat_by_address, &addr, addr.sin_len); + if (jail) { + jail->in_octets += octets; + ++jail->in_packets; + return; + } + + /* Try outgoing */ + memcpy (&addr.sin_addr, &hdr->src, sizeof (addr.sin_addr)); + + jail = hsh_get (jaildat_by_address, &addr, addr.sin_len); + if (jail) { + jail->out_octets += octets; + ++jail->out_packets; + return; + } +} + +static void +process_ip6 (const struct ip6hdr *hdr, uint32_t octets) +{ + struct sockaddr_in6 addr; + struct jaildat *jail; + + ASSERT (hdr); + + /* Try incoming */ + memset (&addr, 0, sizeof (addr)); + addr.sin6_family = AF_INET6; + addr.sin6_len = sizeof (addr); + addr.sin6_port = 0; + memcpy (&addr.sin6_addr, &hdr->dst, sizeof (addr.sin6_addr)); + + jail = hsh_get (jaildat_by_address, &addr, addr.sin6_len); + if (jail) { + jail->in_octets += octets; + ++jail->in_packets; + return; + } + + /* Try outgoing */ + memcpy (&addr.sin6_addr, &hdr->src, sizeof (addr.sin6_addr)); + + jail = hsh_get (jaildat_by_address, &addr, addr.sin6_len); + if (jail) { + jail->out_octets += octets; + ++jail->out_packets; + return; + } +} + +static void +monitor_packet (u_char *data, const struct pcap_pkthdr *hdr, const u_char *bytes) +{ + struct ethhdr *eth; + int minlen, octets, type; + + /* Short packet, don't care */ + if (hdr->len < sizeof (struct ethhdr)) + return; + + eth = (struct ethhdr*)bytes; + bytes += sizeof (struct ethhdr); + octets = hdr->len - sizeof (struct ethhdr); + type = ntohs (eth->type); + + /* IPv4 packet? */ + if (type == 0x0800) { + minlen = (sizeof (struct ethhdr) + sizeof (struct ip4hdr)); + if (hdr->len >= minlen) { + ASSERT (hdr->caplen >= minlen); + process_ip4 ((const struct ip4hdr*)bytes, octets); + } + + /* IPv6 packet? */ + } else if (type == 0x86DD) { + minlen = (sizeof (struct ethhdr) + sizeof (struct ip6hdr)); + if (hdr->len >= minlen) { + ASSERT (hdr->caplen >= minlen); + process_ip6 ((const struct ip6hdr*)bytes, octets); + } + } +} + +static void +monitor_io (int fd, void *data) +{ + struct monitor* mon = (struct monitor*)data; + int n_packets; + + n_packets = pcap_dispatch (mon->handle, -1, monitor_packet, (u_char*)mon); + if (n_packets < 0) + emsg ("couldn't capture packets in monitor: %s", pcap_geterr (mon->handle)); +} + +static void +monitor_free (struct monitor *mon) +{ + ASSERT (mon); + + if (mon->device) + free (mon->device); + if (mon->watch) + fd_deselect (mon->watch); + if (mon->handle) + pcap_close (mon->handle); + if (mon->filter_valid) + pcap_freecode (&mon->filter); + + TAILQ_REMOVE (&monitors, mon, link); + free (mon); +} + +static struct monitor* +monitor_create (const char *device) +{ + char errbuf[PCAP_ERRBUF_SIZE]; + struct monitor* mon = NULL; + int success = 0; + int fd; + + ASSERT (device); + ASSERT (network_filter); + + mon = calloc (1, sizeof (struct monitor)); + if (!mon) { + emsg ("couldn't allocate monitor: out of memory"); + goto cleanup; + } + + TAILQ_INSERT_TAIL(&monitors, mon, link); + mon->device = strdup (device); + + mon->handle = pcap_open_live (mon->device, SNAP_LEN, 0, 100, errbuf); + if (!mon->handle) { + emsg ("couldn't open monitor on %s: %s", mon->device, errbuf); + goto cleanup; + } + + if (pcap_compile (mon->handle, &mon->filter, network_filter, 1, 0) < 0) { + emsg ("couldn't compile monitor expression: %s", pcap_geterr (mon->handle)); + goto cleanup; + } + + mon->filter_valid = 1; + if (pcap_setfilter (mon->handle, &mon->filter) < 0) { + emsg ("couldn't setup monitor expression: %s", pcap_geterr (mon->handle)); + goto cleanup; + } + + if (pcap_setnonblock (mon->handle, 1, errbuf) < 0) { + emsg ("couldn't set monitor in non-block mode: %s", errbuf); + goto cleanup; + } + + fd = pcap_get_selectable_fd (mon->handle); + if (fd < 0) { + emsg ("couldn't get selectable monitor: %s", pcap_geterr (mon->handle)); + goto cleanup; + } + + mon->watch = fd_select (fd, monitor_io, mon, module); + if (!mon->watch) { + emsg ("couldn't listen to monitor: %s", strerror (errno)); + goto cleanup; + } + + success = 1; + +cleanup: + if (!success && mon) { + monitor_free (mon); + mon = NULL; + } + + return mon; +} + +static void +monitor_ref (struct monitor *mon) +{ + ASSERT (mon); + ASSERT (mon->refs >= 0); + ++mon->refs; +} + +static void +monitor_unref (struct monitor *mon) +{ + ASSERT (mon); + + --mon->refs; + ASSERT (mon->refs >= 0); + + if (mon->refs == 0) + monitor_free (mon); +} + +static struct monitor* +monitor_for_device (const char *device) +{ + struct monitor *mon; + + ASSERT (device); + + while ((mon = TAILQ_FIRST (&monitors)) != NULL) { + ASSERT (mon->device); + if (strcmp (mon->device, device) == 0) + return mon; + } + + return monitor_create (device); +} + +static void* +monitor_addr_enumerator (struct ifreq *ifr, void *data) +{ + struct sockaddr *addr = (struct sockaddr*)data; + int match = 0; + + ASSERT (ifr); + ASSERT (addr); + + switch (ifr->ifr_addr.sa_family) { + case AF_INET: + if (addr->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in*)addr; + if (memcmp (&(sin->sin_addr), &(((struct sockaddr_in*)&ifr->ifr_addr)->sin_addr), + sizeof (sin->sin_addr)) == 0) + match = 1; + } + break; + + case AF_INET6: + if (addr->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)addr; + if (memcmp (&sin6->sin6_addr, &(((struct sockaddr_in6*)&ifr->ifr_addr)->sin6_addr), + sizeof (sin6->sin6_addr)) == 0) + match = 1; + } + break; + + default: + break; + }; + + if (!match) + return NULL; + + return monitor_for_device (ifr->ifr_name); +} + +static struct monitor* +monitor_for_address (struct sockaddr *addr) +{ + return (struct monitor*)enumerate_ifs (monitor_addr_enumerator, addr); +} + +static int +monitor_test_filter (const char *filter) +{ + struct bpf_program bpf; + int ret; + + ret = pcap_compile_nopcap (SNAP_LEN, DLT_EN10MB, &bpf, (char*)filter, 1, 0); + if (ret >= 0) + pcap_freecode (&bpf); + + return ret; +} + +/* ----------------------------------------------------------------------------- + * JAIL LOOKUPS + */ + +static void +jail_free (struct jaildat *jail) +{ + ASSERT (jail); + + if (jail->host) + free (jail->host); + jail->host = NULL; + + if (jail->path) + free (jail->path); + jail->path = NULL; + + if (jail->monitor) + monitor_unref (jail->monitor); + jail->monitor = NULL; + + if (jail->index) + TAILQ_REMOVE (&jaildats, jail, link); + + free (jail); +} + +static int +jail_update (struct jaildat *jail, const char *host, + const char *path, struct in_addr *addr) +{ + struct monitor *mon; + char *dup; + + ASSERT (jail); + + if (!host) + host = ""; + + if (!jail->host || strcmp (jail->host, host) != 0) { + dup = strdup (host); + if (!dup) + return -1; + if (jail->host) { + hsh_rem (jaildat_by_host, jail->host, HSH_KEY_STRING); + free (jail->host); + } + jail->host = dup; + hsh_set (jaildat_by_host, jail->host, HSH_KEY_STRING, jail); + } + + if (!path) + path = ""; + if (!jail->path || strcmp (jail->path, path) != 0) { + dup = strdup (path); + if (!dup) + return -1; + if (jail->path) + free (jail->path); + jail->path = dup; + } + + 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; + } + } + + return 0; +} + +static struct jaildat* +jail_alloc (const char *host, const char *path, struct in_addr *addr) +{ + struct jaildat *jail; + + jail = (struct jaildat*)calloc (1, sizeof (struct jaildat)); + if (!jail) + return NULL; + + if (jail_update (jail, host, path, addr) < 0) { + jail_free (jail); + return NULL; + } + + jaildat_count++; + jail->index = jaildat_count; + INSERT_OBJECT_INT (jail, &jaildats); + + return jail; +} + +static void +jail_refresh_all (void* unused) +{ + struct xprison *sxp, *xp; + struct in_addr in; + struct jaildat *jail, *tmp; + size_t i, len; + + /* Get the length of the list */ + if (sysctlbyname ("security.jail.list", NULL, &len, NULL, 0) == -1) { + emsg ("couldn't lookup jail list: %s", strerror (errno)); + return; + } + + /* Retrieve actual data */ + for (i = 0; i < 4; i++) { + if (len <= 0) + return; + sxp = xp = malloc (len); + if (sxp == NULL) { + emsg ("out of memory"); + return; + } + + if (sysctlbyname ("security.jail.list", xp, &len, NULL, 0) == -1) { + free (sxp); + sxp = NULL; + if (errno == ENOMEM) + continue; + } + + if (sxp == NULL) { + emsg ("couldn't retrieve jail list: %s", strerror (errno)); + return; + } + + 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_host, xp->pr_path, &in); + else + jail_update (jail, xp->pr_host, xp->pr_path, &in); + + jail->mark = 0; + xp++; + } + + /* Sweep any jails that are no longer */ + TAILQ_FOREACH_SAFE (jail, &jaildats, link, tmp) { + if (jail->mark) + jail_free (jail); + } + + free (sxp); +} + +/* ----------------------------------------------------------------------------- + * CALLBACKS/CONFIG + */ + +int +op_jailconfig (struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + int r = SNMP_ERR_NOERROR; + + switch (which) { + case LEAF_jailNetworkFilter: + + if (op == SNMP_OP_GET) + return string_get (value, network_filter, -1); + + /* Remainder only at initialization */ + if (community != COMM_INITIALIZE) + return SNMP_ERR_NOT_WRITEABLE; + + switch (op) { + case SNMP_OP_SET: + if ((r = string_save (value, ctx, -1, &network_filter)) == SNMP_ERR_NOERROR) { + if (monitor_test_filter (network_filter) < 0) + r = SNMP_ERR_GENERR; + } + if (r != SNMP_ERR_NOERROR) + string_rollback (ctx, &network_filter); + break; + case SNMP_OP_COMMIT: + string_commit (ctx); + break; + case SNMP_OP_ROLLBACK: + string_rollback (ctx, &network_filter); + break; + default: + ASSERT(0); + break; + }; + + return r; + + default: + break; + }; + + ASSERT(0); + return -1; +} + +int +op_jailentry (struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + struct jaildat *jail = NULL; + + switch (op) { + case SNMP_OP_GETNEXT: + jail = NEXT_OBJECT_INT (&jaildats, &value->var, sub); + if (jail == NULL) + return SNMP_ERR_NOSUCHNAME; + value->var.len = sub + 1; + value->var.subs[sub] = jail->index; + break; + + case SNMP_OP_GET: + jail = FIND_OBJECT_INT (&jaildats, &value->var, sub); + if (jail == NULL) + return SNMP_ERR_NOSUCHNAME; + break; + + default: + jail = FIND_OBJECT_INT (&jaildats, &value->var, sub); + break; + }; + + if (op != SNMP_OP_GET && op != SNMP_OP_GETNEXT) + return SNMP_ERR_NOT_WRITEABLE; + + switch (which) { + case LEAF_jailIndex: + value->v.integer = jail->index; + return SNMP_ERR_NOERROR; + case LEAF_jailHost: + return string_get (value, jail->host, -1); + case LEAF_jailInOctets: + value->v.uint32 = jail->in_octets; + return SNMP_ERR_NOERROR; + case LEAF_jailInPackets: + value->v.uint32 = jail->in_packets; + return SNMP_ERR_NOERROR; + case LEAF_jailOutOctets: + value->v.uint32 = jail->out_octets; + return SNMP_ERR_NOERROR; + case LEAF_jailOutPackets: + value->v.uint32 = jail->out_packets; + return SNMP_ERR_NOERROR; + default: + ASSERT (0); + return SNMP_ERR_NOSUCHNAME; + }; +} + +int +op_jail (struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + + switch (op) { + case SNMP_OP_GET: + break; + + case SNMP_OP_SET: + return SNMP_ERR_NOT_WRITEABLE; + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + return SNMP_ERR_NOERROR; + + default: + ASSERT(0); + break; + }; + + switch (which) { + case LEAF_jailCount: + value->v.integer = jaildat_count; + break; + + default: + ASSERT(0); + break; + }; + + return SNMP_ERR_NOERROR; +} + + +/* ----------------------------------------------------------------------------- + * MODULE + */ + +/* Called, when the module is to be unloaded after it was successfully loaded */ +static int +module_fini (void) +{ + struct jaildat *jail; + struct monitor *mon; + + if (reg_index) + or_unregister (reg_index); + + if (network_filter) + free (network_filter); + network_filter = NULL; + + if (jaildat_by_address) + hsh_free (jaildat_by_address); + jaildat_by_address = NULL; + + if (jaildat_by_host) + hsh_free (jaildat_by_host); + jaildat_by_host = NULL; + + while ((jail = TAILQ_FIRST(&jaildats)) != NULL) + jail_free (jail); + + while ((mon = TAILQ_FIRST(&monitors)) != NULL) + monitor_free (mon); + + if (timer_refresh) + timer_stop (timer_refresh); + timer_refresh = NULL; + + return 0; +} + +/* the initialisation function */ +static int +module_init (struct lmodule *mod, int argc, char *argv[]) +{ + int success = 0; + + module = mod; + + if (argc != 0) { + syslog (LOG_ERR, "bad number of arguments for %s", __func__); + return EINVAL; + } + + network_filter = strdup ("ip or ip6"); + if (!network_filter) + goto cleanup; + + jaildat_by_host = hsh_create (); + if (!jaildat_by_host) + goto cleanup; + + jaildat_by_address = hsh_create (); + if (!jaildat_by_address) + goto cleanup; + + success = 1; + +cleanup: + if (!success) { + emsg ("error initializing: out of memory"); + module_fini (); + return ENOMEM; + } + + return 0; +} + +/* Module is started */ +static void +module_start (void) +{ + reg_index = or_register (&oid_jails, "The MIB for jail interface data.", module); + + jail_refresh_all (NULL); + + timer_refresh = timer_start_repeat (500, 500, jail_refresh_all, NULL, module); + if (!timer_refresh) + emsg ("couldn't setup timer to refresh jails"); +} + +const struct snmp_module config = { + .comment = "This module implements SNMP monitoring of jails", + .init = module_init, + .start = module_start, + .fini = module_fini, + .tree = jails_ctree, + .tree_size = jails_CTREE_SIZE, +}; + diff --git a/module/jails-tree.def b/module/jails-tree.def new file mode 100644 index 0000000..fc70afd --- /dev/null +++ b/module/jails-tree.def @@ -0,0 +1,64 @@ +# +# Copyright (c) 2006, Stefan Walter +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above +# copyright notice, this list of conditions and the +# following disclaimer. +# * Redistributions in binary form must reproduce the +# above copyright notice, this list of conditions and +# the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# * The names of contributors to this software may not be +# used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. +# +# +# CONTRIBUTORS +# Stef Walter <stef@memberwebs.com> +# + +(1 internet + (4 private + (1 enterprises + (12325 fokus + (1 begemot + (1111 jails + (1 jailCount INTEGER op_jail GET) + (2 jailTable + (1 jailEntry : INTEGER op_jailentry + (0 jailIndex INTEGER GET) + (1 jailHost OCTETSTRING GET) + (10 jailInOctets COUNTER64 GET) + (11 jailInPackets COUNTER64 GET) + (12 jailOutOctets COUNTER64 GET) + (13 jailOutPackets COUNTER64 GET) + ) + ) + + # Valid only during configuration + (100 jailNetworkFilter OCTETSTRING op_jailconfig GET SET) + ) + ) + ) + ) + ) +) + diff --git a/module/usuals.h b/module/usuals.h new file mode 100644 index 0000000..e975dcd --- /dev/null +++ b/module/usuals.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2006, Stefan Walter + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * + * CONTRIBUTORS + * Stef Walter <stef@memberwebs.com> + */ + +#ifndef __USUALS_H__ +#define __USUALS_H__ + +#include <sys/types.h> + +#include "config.h" + +#include <errno.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#define countof(x) (sizeof(x) / sizeof(x[0])) + +#ifdef _DEBUG + #include "assert.h" + #define ASSERT(x) assert(x) +#else + #define ASSERT(x) +#endif + +#endif /* __USUALS_H__ */ |