summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2008-03-02 18:22:41 +0000
committerStef Walter <stef@memberwebs.com>2008-03-02 18:22:41 +0000
commit92034c311a745284c6a5675fe42dc84af21bd2a6 (patch)
treeff13e3f9c9ccb240618ff2075e3093d5bae127b5
Initial import
-rw-r--r--AUTHORS1
-rw-r--r--COPYING38
-rw-r--r--ChangeLog2
-rw-r--r--Makefile.am6
-rw-r--r--NEWS1
-rw-r--r--README3
-rwxr-xr-xautogen.sh11
-rw-r--r--common/hash.c381
-rw-r--r--common/hash.h142
-rw-r--r--configure.in69
-rw-r--r--doc/BEGEMOT-MIB.txt59
-rw-r--r--doc/FOKUS-MIB.txt57
-rw-r--r--doc/JAILS-MIB.txt118
-rw-r--r--doc/Makefile.am12
-rw-r--r--doc/bsnmp-jails.8105
-rwxr-xr-xdoc/man2html.pl230
-rw-r--r--module/Makefile.am19
-rw-r--r--module/bsnmp-jails.c947
-rw-r--r--module/jails-tree.def64
-rw-r--r--module/usuals.h68
20 files changed, 2333 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..b122b64
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Stef Walter <stef@memberwebs.com>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..126ddab
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,38 @@
+LICENSE
+
+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.
+
+
+SUPPORT
+
+Send bug reports to: <stef@memberwebs.com>
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..b2a0957
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,2 @@
+0.1
+ - Initial Release
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..8352aa0
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,6 @@
+EXTRA_DIST = common
+SUBDIRS = module doc
+
+dist-hook:
+ rm -rf `find $(distdir)/ -name .svn`
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..c7ab92a
--- /dev/null
+++ b/NEWS
@@ -0,0 +1 @@
+See ChangeLog \ No newline at end of file
diff --git a/README b/README
new file mode 100644
index 0000000..f30192a
--- /dev/null
+++ b/README
@@ -0,0 +1,3 @@
+This is a module for bsnmpd (included with FreeBSD 6.x, installable on 5.x):
+
+http://people.freebsd.org/~harti/bsnmp/
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..100e70d
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,11 @@
+#!/bin/sh -ex
+
+set -ex
+
+aclocal
+autoheader
+libtoolize --force
+automake -a
+autoconf
+./configure --enable-maintainer-mode "$@"
+
diff --git a/common/hash.c b/common/hash.c
new file mode 100644
index 0000000..9acd2df
--- /dev/null
+++ b/common/hash.c
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2004, 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.
+ */
+
+/*
+ * Originally from apache 2.0
+ * Modifications for general use by <stef@memberwebs.com>
+ */
+
+/* Copyright 2000-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include "hash.h"
+
+#define KEY_DATA(he) ((he)->key)
+
+/*
+ * The internal form of a hash table.
+ *
+ * The table is an array indexed by the hash of the key; collisions
+ * are resolved by hanging a linked list of hash entries off each
+ * element of the array. Although this is a really simple design it
+ * isn't too bad given that pools have a low allocation overhead.
+ */
+
+typedef struct hsh_entry_t hsh_entry_t;
+
+struct hsh_entry_t
+{
+ hsh_entry_t* next;
+ unsigned int hash;
+ const void* key;
+ size_t klen;
+ const void* val;
+};
+
+/*
+ * Data structure for iterating through a hash table.
+ *
+ * We keep a pointer to the next hash entry here to allow the current
+ * hash entry to be freed or otherwise mangled between calls to
+ * hsh_next().
+ */
+struct hsh_index_t
+{
+ hsh_t* ht;
+ hsh_entry_t* ths;
+ hsh_entry_t* next;
+ unsigned int index;
+};
+
+/*
+ * The size of the array is always a power of two. We use the maximum
+ * index rather than the size so that we can use bitwise-AND for
+ * modular arithmetic.
+ * The count of hash entries may be greater depending on the chosen
+ * collision rate.
+ */
+struct hsh_t
+{
+ hsh_entry_t** array;
+ hsh_index_t iterator; /* For hsh_first(...) */
+ unsigned int count;
+ unsigned int max;
+};
+
+
+#define INITIAL_MAX 15 /* tunable == 2^n - 1 */
+#define int_malloc malloc
+#define int_calloc calloc
+#define int_free free
+
+/*
+ * Hash creation functions.
+ */
+
+static hsh_entry_t** alloc_array(hsh_t* ht, unsigned int max)
+{
+ return (hsh_entry_t**)int_calloc(sizeof(*(ht->array)), (max + 1));
+}
+
+hsh_t* hsh_create()
+{
+ hsh_t* ht = int_malloc(sizeof(hsh_t));
+ if(ht)
+ {
+ ht->count = 0;
+ ht->max = INITIAL_MAX;
+ ht->array = alloc_array(ht, ht->max);
+ if(!ht->array)
+ {
+ int_free(ht);
+ return NULL;
+ }
+ }
+ return ht;
+}
+
+void hsh_free(hsh_t* ht)
+{
+ hsh_index_t* hi;
+
+ for(hi = hsh_first(ht); hi; hi = hsh_next(hi))
+ int_free(hi->ths);
+
+ if(ht->array)
+ int_free(ht->array);
+
+ int_free(ht);
+}
+
+/*
+ * Hash iteration functions.
+ */
+
+hsh_index_t* hsh_next(hsh_index_t* hi)
+{
+ hi->ths = hi->next;
+ while(!hi->ths)
+ {
+ if(hi->index > hi->ht->max)
+ return NULL;
+
+ hi->ths = hi->ht->array[hi->index++];
+ }
+ hi->next = hi->ths->next;
+ return hi;
+}
+
+hsh_index_t* hsh_first(hsh_t* ht)
+{
+ hsh_index_t* hi = &ht->iterator;
+
+ hi->ht = ht;
+ hi->index = 0;
+ hi->ths = NULL;
+ hi->next = NULL;
+ return hsh_next(hi);
+}
+
+void* hsh_this(hsh_index_t* hi, const void** key, size_t* klen)
+{
+ if(key)
+ *key = KEY_DATA(hi->ths);
+ if(klen)
+ *klen = hi->ths->klen;
+ return (void*)hi->ths->val;
+}
+
+
+/*
+ * Expanding a hash table
+ */
+
+static int expand_array(hsh_t* ht)
+{
+ hsh_index_t* hi;
+ hsh_entry_t** new_array;
+ unsigned int new_max;
+
+ new_max = ht->max * 2 + 1;
+ new_array = alloc_array(ht, new_max);
+
+ if(!new_array)
+ return 0;
+
+ for(hi = hsh_first(ht); hi; hi = hsh_next(hi))
+ {
+ unsigned int i = hi->ths->hash & new_max;
+ hi->ths->next = new_array[i];
+ new_array[i] = hi->ths;
+ }
+
+ if(ht->array)
+ free(ht->array);
+
+ ht->array = new_array;
+ ht->max = new_max;
+ return 1;
+}
+
+/*
+ * This is where we keep the details of the hash function and control
+ * the maximum collision rate.
+ *
+ * If val is non-NULL it creates and initializes a new hash entry if
+ * there isn't already one there; it returns an updatable pointer so
+ * that hash entries can be removed.
+ */
+
+static hsh_entry_t** find_entry(hsh_t* ht, const void* key, size_t klen, const void* val)
+{
+ hsh_entry_t** hep;
+ hsh_entry_t* he;
+ const unsigned char* p;
+ unsigned int hash;
+ size_t i;
+
+ /*
+ * This is the popular `times 33' hash algorithm which is used by
+ * perl and also appears in Berkeley DB. This is one of the best
+ * known hash functions for strings because it is both computed
+ * very fast and distributes very well.
+ *
+ * The originator may be Dan Bernstein but the code in Berkeley DB
+ * cites Chris Torek as the source. The best citation I have found
+ * is "Chris Torek, Hash function for text in C, Usenet message
+ * <27038@mimsy.umd.edu> in comp.lang.c , October, 1990." in Rich
+ * Salz's USENIX 1992 paper about INN which can be found at
+ * <http://citeseer.nj.nec.com/salz92internetnews.html>.
+ *
+ * The magic of number 33, i.e. why it works better than many other
+ * constants, prime or not, has never been adequately explained by
+ * anyone. So I try an explanation: if one experimentally tests all
+ * multipliers between 1 and 256 (as I did while writing a low-level
+ * data structure library some time ago) one detects that even
+ * numbers are not useable at all. The remaining 128 odd numbers
+ * (except for the number 1) work more or less all equally well.
+ * They all distribute in an acceptable way and this way fill a hash
+ * table with an average percent of approx. 86%.
+ *
+ * If one compares the chi^2 values of the variants (see
+ * Bob Jenkins ``Hashing Frequently Asked Questions'' at
+ * http://burtleburtle.net/bob/hash/hashfaq.html for a description
+ * of chi^2), the number 33 not even has the best value. But the
+ * number 33 and a few other equally good numbers like 17, 31, 63,
+ * 127 and 129 have nevertheless a great advantage to the remaining
+ * numbers in the large set of possible multipliers: their multiply
+ * operation can be replaced by a faster operation based on just one
+ * shift plus either a single addition or subtraction operation. And
+ * because a hash function has to both distribute good _and_ has to
+ * be very fast to compute, those few numbers should be preferred.
+ *
+ * -- Ralf S. Engelschall <rse@engelschall.com>
+ */
+ hash = 0;
+
+ if(klen == HSH_KEY_STRING)
+ {
+ for(p = key; *p; p++)
+ hash = hash * 33 + *p;
+
+ klen = p - (const unsigned char *)key;
+ }
+ else
+ {
+ for(p = key, i = klen; i; i--, p++)
+ hash = hash * 33 + *p;
+ }
+
+ /* scan linked list */
+ for(hep = &ht->array[hash & ht->max], he = *hep;
+ he; hep = &he->next, he = *hep)
+ {
+ if(he->hash == hash &&
+ he->klen == klen &&
+ memcmp(KEY_DATA(he), key, klen) == 0)
+ break;
+ }
+
+ if(he || !val)
+ return hep;
+
+ /* add a new entry for non-NULL val */
+ he = int_malloc(sizeof(*he));
+
+ if(he)
+ {
+ /* Key points to external data */
+ he->key = key;
+ he->klen = klen;
+
+ he->next = NULL;
+ he->hash = hash;
+ he->val = val;
+
+ *hep = he;
+ ht->count++;
+ }
+
+ return hep;
+}
+
+void* hsh_get(hsh_t* ht, const void *key, size_t klen)
+{
+ hsh_entry_t** he = find_entry(ht, key, klen, NULL);
+
+ if(he && *he)
+ return (void*)((*he)->val);
+ else
+ return NULL;
+}
+
+int hsh_set(hsh_t* ht, const void* key, size_t klen, void* val)
+{
+ hsh_entry_t** hep = find_entry(ht, key, klen, val);
+
+ if(hep && *hep)
+ {
+ /* replace entry */
+ (*hep)->val = val;
+
+ /* check that the collision rate isn't too high */
+ if(ht->count > ht->max)
+ {
+ if(!expand_array(ht))
+ return 0;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+void* hsh_rem(hsh_t* ht, const void* key, size_t klen)
+{
+ hsh_entry_t** hep = find_entry(ht, key, klen, NULL);
+ void* val = NULL;
+
+ if(hep && *hep)
+ {
+ hsh_entry_t* old = *hep;
+ *hep = (*hep)->next;
+ --ht->count;
+ val = (void*)old->val;
+ free(old);
+ }
+
+ return val;
+}
+
+unsigned int hsh_count(hsh_t* ht)
+{
+ return ht->count;
+}
+
diff --git a/common/hash.h b/common/hash.h
new file mode 100644
index 0000000..4dc37b2
--- /dev/null
+++ b/common/hash.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2004, 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.
+ */
+
+/*
+ * Originally from apache 2.0
+ * Modifications for general use by <stef@memberwebs.com>
+ */
+
+/* Copyright 2000-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __HSH_H__
+#define __HSH_H__
+
+/*
+ * ARGUMENT DOCUMENTATION
+ *
+ * ht: The hashtable
+ * key: Pointer to the key value
+ * klen: The length of the key
+ * val: Pointer to the value
+ * hi: A hashtable iterator
+ * stamp: A unix timestamp
+ */
+
+
+/* ----------------------------------------------------------------------------------
+ * TYPES
+ */
+
+/* Abstract type for hash tables. */
+typedef struct hsh_t hsh_t;
+
+/* Abstract type for scanning hash tables. */
+typedef struct hsh_index_t hsh_index_t;
+
+/* -----------------------------------------------------------------------------
+ * MAIN
+ */
+
+/*
+ * hsh_create : Create a hash table
+ * - returns an allocated hashtable
+ */
+hsh_t* hsh_create();
+
+/*
+ * hsh_free : Free a hash table
+ */
+void hsh_free(hsh_t* ht);
+
+/*
+ * hsh_count: Number of values in hash table
+ * - returns the number of entries in hash table
+ */
+unsigned int hsh_count(hsh_t* ht);
+
+/*
+ * hsh_get: Retrieves a value from the hash table
+ * - returns the value of the entry
+ */
+void* hsh_get(hsh_t* ht, const void* key, size_t klen);
+
+/*
+ * hsh_set: Set a value in the hash table
+ * - returns 1 if the entry was added properly
+ */
+int hsh_set(hsh_t* ht, const void* key, size_t klen, void* val);
+
+/*
+ * hsh_rem: Remove a value from the hash table
+ * - returns the value of the removed entry
+ */
+void* hsh_rem(hsh_t* ht, const void* key, size_t klen);
+
+/*
+ * hsh_first: Start enumerating through the hash table
+ * - returns a hash iterator
+ */
+hsh_index_t* hsh_first(hsh_t* ht);
+
+/*
+ * hsh_next: Enumerate through hash table
+ * - returns the hash iterator or null when no more entries
+ */
+hsh_index_t* hsh_next(hsh_index_t* hi);
+
+/*
+ * hsh_this: While enumerating get current value
+ * - returns the value that the iterator currently points to
+ */
+void* hsh_this(hsh_index_t* hi, const void** key, size_t* klen);
+
+/*
+ * 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)
+
+#endif /* __HSH_H__ */
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..ba1602c
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,69 @@
+# Process this file with autoconf to produce a configure script.
+AC_INIT(bsnmp-jails, 0.1, stef@memberwebs.com)
+AM_INIT_AUTOMAKE(bsnmp-jails, 0.1)
+
+AC_CONFIG_SRCDIR([module/bsnmp-jails.c])
+AM_CONFIG_HEADER([config.h])
+
+LDFLAGS="$LDFLAGS -L/usr/local/lib"
+CFLAGS="$CFLAGS -I/usr/local/include"
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+AC_CHECK_PROG(GENSNMPTREE, gensnmptree, "gensnmptree")
+if test -z "$GENSNMPTREE"; then
+ echo "ERROR: gensnmptree program not found."
+ exit 1
+fi
+
+# Debug mode
+AC_ARG_ENABLE(debug,
+ AC_HELP_STRING([--enable-debug],
+ [Compile binaries in debug mode]))
+
+if test "$enable_debug" = "yes"; then
+ CFLAGS="$CFLAGS -g -O0 -Wall"
+ AC_DEFINE_UNQUOTED(_DEBUG, 1, [In debug mode])
+ echo "enabling debug compile mode"
+fi
+
+# Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS([netinet/in.h netinet/in_systm.h netinet/ip.h arpa/inet.h], ,
+ [echo "ERROR: required netinet header not found."; exit 1],
+ [[
+ #include <sys/types.h>
+ #if HAVE_NETINET_IN_H
+ #include <netinet/in.h>
+ #endif
+ #if HAVE_NETINET_IN_SYSTM_H
+ #include <netinet/in_systm.h>
+ #endif
+ #if HAVE_NETINET_IP_H
+ #include <netinet/ip.h>
+ #endif
+ ]])
+AC_CHECK_HEADERS([sys/queue.h sys/limits.h sys/stat.h sys/time.h], ,
+ [echo "ERROR: required header not found."; exit 1])
+AC_CHECK_HEADERS([bsnmp/snmpmod.h], ,
+ [echo "ERROR: required bsnmp header not found." exit 1])
+AC_CHECK_HEADERS([pcap.h], ,
+ [echo "ERROR: required pcap header not found." exit 1])
+
+# Check for libraries
+AC_SEARCH_LIBS(pcap_open_live, pcap, ,
+ [ echo "Must have a pcap library available"; exit 2 ] )
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_SIZE_T
+
+# Checks for library functions.
+AC_FUNC_MALLOC
+AC_FUNC_MEMCMP
+
+AC_CONFIG_FILES([Makefile module/Makefile doc/Makefile])
+AC_OUTPUT
+
diff --git a/doc/BEGEMOT-MIB.txt b/doc/BEGEMOT-MIB.txt
new file mode 100644
index 0000000..9d99eab
--- /dev/null
+++ b/doc/BEGEMOT-MIB.txt
@@ -0,0 +1,59 @@
+--
+-- Copyright (c) 2001-2003
+-- Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+-- All rights reserved.
+--
+-- Author: Harti Brandt <harti@freebsd.org>
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions
+-- are met:
+-- 1. Redistributions of source code must retain the above copyright
+-- notice, this list of conditions and the following disclaimer.
+-- 2. 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.
+--
+-- THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+--
+-- $Begemot: bsnmp/snmpd/BEGEMOT-MIB.txt,v 1.5 2004/08/06 08:47:07 brandt Exp $
+--
+-- Begemot private definitions and root.
+--
+BEGEMOT-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+ MODULE-IDENTITY
+ FROM SNMPv2-SMI
+ fokus
+ FROM FOKUS-MIB;
+
+begemot MODULE-IDENTITY
+ LAST-UPDATED "200201300000Z"
+ ORGANIZATION "Fraunhofer FOKUS, CATS"
+ CONTACT-INFO
+ " Hartmut Brandt
+
+ Postal: Fraunhofer Institute for Open Communication Systems
+ Kaiserin-Augusta-Allee 31
+ 10589 Berlin
+ Germany
+
+ Fax: +49 30 3463 7352
+
+ E-mail: harti@freebsd.org"
+ DESCRIPTION
+ "The root of the Begemot subtree of the fokus tree."
+ ::= { fokus 1 }
+
+END
diff --git a/doc/FOKUS-MIB.txt b/doc/FOKUS-MIB.txt
new file mode 100644
index 0000000..d4671e8
--- /dev/null
+++ b/doc/FOKUS-MIB.txt
@@ -0,0 +1,57 @@
+--
+-- Copyright (c) 2001-2003
+-- Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+-- All rights reserved.
+--
+-- Author: Harti Brandt <harti@freebsd.org>
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions
+-- are met:
+-- 1. Redistributions of source code must retain the above copyright
+-- notice, this list of conditions and the following disclaimer.
+-- 2. 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.
+--
+-- THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+--
+-- $Begemot: bsnmp/snmpd/FOKUS-MIB.txt,v 1.5 2004/08/06 08:47:08 brandt Exp $
+--
+-- Begemot private definitions and fokus root.
+--
+FOKUS-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+ MODULE-IDENTITY, enterprises
+ FROM SNMPv2-SMI;
+
+fokus MODULE-IDENTITY
+ LAST-UPDATED "200202050000Z"
+ ORGANIZATION "Fraunhofer FOKUS, CATS"
+ CONTACT-INFO
+ " Hartmut Brandt
+
+ Postal: Fraunhofer Institute for Open Communication Systems
+ Kaiserin-Augusta-Allee 31
+ 10589 Berlin
+ Germany
+
+ Fax: +49 30 3463 7352
+
+ E-mail: harti@freebsd.org"
+ DESCRIPTION
+ "The root of the Fokus enterprises tree."
+ ::= { enterprises 12325 }
+
+END
diff --git a/doc/JAILS-MIB.txt b/doc/JAILS-MIB.txt
new file mode 100644
index 0000000..90ed4a9
--- /dev/null
+++ b/doc/JAILS-MIB.txt
@@ -0,0 +1,118 @@
+--
+-- Copyright (c) 2008
+-- Stefan Walter <stef@memberwebs.com>
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions
+-- are met:
+-- 1. Redistributions of source code must retain the above copyright
+-- notice, this list of conditions and the following disclaimer.
+-- 2. 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.
+--
+-- THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+--
+PING-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+ MODULE-IDENTITY, OBJECT-TYPE, Counter64, Integer32, TimeTicks, Unsigned32
+ FROM SNMPv2-SMI
+ begemot
+ FROM BEGEMOT-MIB;
+
+jails MODULE-IDENTITY
+ LAST-UPDATED "200903010000Z"
+ ORGANIZATION "Stef Walter"
+ CONTACT-INFO "stef@memberwebs.com"
+ DESCRIPTION "The MIB for the bsnmp-jail module."
+
+ ::= { begemot 1111 }
+
+-- --------------------------------------------------------------------------
+
+jailCount OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION "The number jails running on the system."
+ ::= { jails 1 }
+
+jailTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF JailEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION "A list of entries representing jails running on the system. The number of entries is given by the value of jailCount."
+ ::= { jails 2 }
+
+jailEntry OBJECT-TYPE
+ SYNTAX JailEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION "An entry containing information about a running jail."
+ INDEX { jailIndex }
+ ::= { jailTable 1 }
+
+JailEntry ::=
+ SEQUENCE {
+ jailIndex Integer32,
+ jailHost OCTET STRING,
+ jailInOctets Counter64,
+ jailInPackets Counter64,
+ jailOutOctets Counter64,
+ jailOutPackets Counter64,
+ }
+
+jailIndex OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION "Index of this jailEntry."
+ ::= { jailEntry 0 }
+
+jailHost OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION "The host name of this jail."
+ ::= { jailEntry 1 }
+
+jailInOctets OBJECT-TYPE
+ SYNTAX Counter64
+ MAX-ACESS read-only
+ STATUS current
+ DESCRIPTION "Number of octets received by this jail."
+ ::= { jailEntry 10 }
+
+jailInPackets OBJECT-TYPE
+ SYNTAX Counter64
+ MAX-ACESS read-only
+ STATUS current
+ DESCRIPTION "Number of packets received by this jail."
+ ::= { jailEntry 11 }
+
+jailOutOctets OBJECT-TYPE
+ SYNTAX Counter64
+ MAX-ACESS read-only
+ STATUS current
+ DESCRIPTION "Number of octets sent by this jail."
+ ::= { jailEntry 12 }
+
+jailOutPackets OBJECT-TYPE
+ SYNTAX Counter64
+ MAX-ACESS read-only
+ STATUS current
+ DESCRIPTION "Number of packets sent by this jail."
+ ::= { jailEntry 13 }
+
+END
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..9db5f8a
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,12 @@
+
+man_MANS = bsnmp-jails.8
+
+# Simple way to make docs
+html:
+ perl man2html.pl bsnmp-jails.8 > bsnmp-jails.8.html
+
+EXTRA_DIST = $(man_MANS) \
+ man2html.pl \
+ BEGEMOT-MIB.txt \
+ FOKUS-MIB.txt \
+ JAILS-MIB.txt
diff --git a/doc/bsnmp-jails.8 b/doc/bsnmp-jails.8
new file mode 100644
index 0000000..d3a73a6
--- /dev/null
+++ b/doc/bsnmp-jails.8
@@ -0,0 +1,105 @@
+.\"
+.\" 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
+.\" Stef Walter <stef@memberwebs.com>
+.\"
+.Dd March, 2008
+.Dt bsnmp-jails 8
+.Os bsnmp-jails
+.Sh NAME
+.Nm bsnmp-jails
+.Nd an SNMP module provides statistics regarding FreeBSD jails running on the system.
+.Sh DESCRIPTION
+.Nm
+is a module for
+.Xr bsnmpd 1
+which monitors network and other statistics for FreeBSD jails running on the system.
+These statistics are gathered by the module.
+.Pp
+.Sh MIBS
+The counters will be available as a table under the following MIB:
+.Bd -literal -offset indent
+ .1.3.6.1.4.1.12325.1.204
+.Ed
+.Pp
+Or if the appropriate MIB.txt files have been installed:
+.Bd -literal -offset indent
+ enterprises.fokus.begemot.jails
+.Ed
+.Pp
+The following SNMP MIBs are available for use (where X is the counter index):
+.Bl -tag -width Fl
+.It Ar jails.jailCount
+The number of jails running on the system.
+.It Ar jails.jailTable.jailEntry.jailIndex.X
+The index of the jail in the table.
+.It Ar jails.jailTable.jailEntry.jailHost.X
+The hostname of the jail.
+.It Ar jails.jailTable.jailEntry.jailInOctets.X
+The number of octets received by the jail over the network.
+.It Ar jails.jailTable.jailEntry.jailInPackets.X
+The number of packets received by the jail over the network.
+.It Ar jails.jailTable.jailEntry.jailOutOctets.X
+The number of octets sent by the jail over the network.
+.It Ar jails.jailTable.jailEntry.jailOutPackets.X
+The number of packets sent by the jail over the network.
+.It Ar jails.jailNetworkFilter
+A tcpdump style filter for the network traffic. Only matched traffic
+is counted in the jail statistics.
+.El
+.Sh OPTIONS
+To activate the
+.Nm
+module you must load the module in
+.Pa /etc/snmpd.config
+.Pp
+You can use the jailNetworkFilter SNMP MIB to configure which traffic
+to count in the jail network statistics.
+.Sh EXAMPLES
+This example configures the module, and excludes traffic to/from the
+10.0.0.0/8 network from the network monitoring.
+.Pp
+The following would be added to
+.Pa /etc/snmpd.config:
+.Bd -literal -offset indent
+begemotSnmpdModulePath."jails" = "/usr/local/lib/snmp_jails.so"
+%jails
+jailNetworkFilter = "not net 10.0.0.0/8"
+.Ed
+.Sh SEE ALSO
+.Xr bsnmpd 1,
+.Xr tcpdump 1
+.Sh AUTHOR
+.An Stef Walter Aq stef@memberwebs.com
+
diff --git a/doc/man2html.pl b/doc/man2html.pl
new file mode 100755
index 0000000..a6a7c3f
--- /dev/null
+++ b/doc/man2html.pl
@@ -0,0 +1,230 @@
+#!/usr/bin/perl
+
+# TODO: We need to make this more resilient
+# currently expects args without enforcing
+
+$FIL = $NAM = $SEC = @ARGV[0];
+
+$NAM =~ s/^([^.]+)\..+$/$1/;
+$SEC =~ s/^.+\.([^.]+)$/$1/;
+
+$command = "groff";
+@args = split(" ", "-Tascii -mdoc $FIL");
+
+$enable_include_links = 0;
+
+man($NAM, $SEC);
+
+sub man {
+ local($name, $section) = @_;
+ local($_, $title, $head, *MAN);
+ local($html_name, $html_section, $prefix);
+ local(@manargs);
+ local($query) = $name;
+
+ # $section =~ s/^([0-9ln]).*$/$1/;
+ $section =~ tr/A-Z/a-z/;
+
+ $prefix = "Man ";
+ if ($alttitle) {
+ $prefix = "";
+ $title = &encode_title($alttitle);
+ $head = &encode_data($alttitle);
+ } elsif ($section) {
+ $title = &encode_title("${name}($section)");
+ $head = &encode_data("${name}($section)");
+ } else {
+ $title = &encode_title("${name}");
+ $head = &encode_data("${name}");
+ }
+
+ print &html_header("$title");
+ print "<H1>Man Page: ${title}</H1>";
+ print "<PRE>\n";
+
+ $html_name = &encode_data($name);
+ $html_section = &encode_data($section);
+
+ #print Dumper($sectionpath);
+ #print "yy $section yy $manpath\n";
+ if ($name =~ /^\s*$/) {
+ print "Empty input, no man page given.\n";
+ return;
+ }
+
+ if (index($name, '*') != -1) {
+ print "Invalid character input '*': $name\n";
+ return;
+ }
+
+ if ($section !~ /^[0-9ln]\w*$/ && $section ne '') {
+ print "Sorry, section `$section' is not valid\n";
+ return;
+ }
+
+ if (!$section) {
+ if ($sectionpath->{$manpath}) {
+ $section = "-S " . $sectionpath->{$manpath}{'path'};
+ } else {
+ $section = '';
+ }
+ } else {
+ if ($sectionpath->{$manpath}{$section}) {
+ $section = "-S " . $sectionpath->{$manpath}{$section};
+ } else {
+ $section = "-S $section";
+ }
+ }
+
+ # print "X $command{'man'} @manargs -- x $name x\n";
+ &proc(*MAN, $command, @args) ||
+ &mydie ("$0: open of $command{'man'} command failed: $!\n");
+ if (eof(MAN)) {
+ # print "X $command{'man'} @manargs -- x $name x\n";
+ print "Sorry, no data found for `$html_name" .
+ ($html_section ? "($html_section)": '') . "'.\n";
+ return;
+ }
+
+ local($space) = 1;
+ local(@sect);
+ local($i, $j);
+ while(<MAN>) {
+ # remove tailing white space
+ if (/^\s+$/) {
+ next if $space;
+ $space = 1;
+ } else {
+ $space = 0;
+ }
+
+ $_ = &encode_data($_);
+ if($enable_include_links &&
+ m,(<B>)?\#include(</B>)?\s+(<B>)?\&lt\;(.*\.h)\&gt\;(</B>)?,) {
+ $match = $4; ($regexp = $match) =~ s/\./\\\./;
+ s,$regexp,\<A HREF=\"$BASE/usr/include/$match\"\>$match\</A\>,;
+ }
+ /^\s/ && # skip headers
+ s,((<[IB]>)?[\w\_\.\-]+\s*(</[IB]>)?\s*\(([1-9ln][a-zA-Z]*)\)),&mlnk($1),oige;
+
+ # detect E-Mail Addreses in manpages
+ if (/\@/) {
+ s/([a-z0-9_\-\.]+\@[a-z0-9\-\.]+\.[a-z]+)/<A HREF="mailto:$1">$1<\/A>/gi;
+ }
+
+ # detect URLs in manpages
+ if (m%tp://%) {
+ s,((ftp|http)://[^\s<>\)]+),<A HREF="$1">$1</A>,gi;
+ }
+
+ if (/^<B>\S+/ && m%^<B>([^<]+)%) {
+ $i = $1; $j = &encode_url($i);
+ s%^<B>([^<]+)</B>%<B>$i</B>%;
+ push(@sect, $1);
+ }
+ print;
+ }
+ close(MAN);
+
+ print "<H6>&nbsp;&nbsp;&nbsp;[ <a href='./'>back</a> | <a href='../../'>home</a> ]</h6>";
+ print "</BODY>\n";
+ print "</HTML>\n";
+
+ # Sleep 0.35 seconds to avoid DoS attacs
+ select undef, undef, undef, 0.35;
+}
+
+# encode unknown data for use in <TITLE>...</TITILE>
+sub encode_title {
+ # like encode_url but less strict (I couldn't find docs on this)
+ local($_) = @_;
+ s/([\000-\031\%\&\<\>\177-\377])/sprintf('%%%02x',ord($1))/eg;
+ $_;
+}
+
+# encode unknown data for use in a URL <A HREF="...">
+sub encode_url {
+ local($_) = @_;
+ # rfc1738 says that ";"|"/"|"?"|":"|"@"|"&"|"=" may be reserved.
+ # And % is the escape character so we escape it along with
+ # single-quote('), double-quote("), grave accent(`), less than(<),
+ # greater than(>), and non-US-ASCII characters (binary data),
+ # and white space. Whew.
+ s/([\000-\032\;\/\?\:\@\&\=\%\'\"\`\<\>\177-\377 ])/sprintf('%%%02x',ord($1))/eg;
+ s/%20/+/g;
+ $_;
+}
+# encode unknown data for use inside markup attributes <MARKUP ATTR="...">
+sub encode_attribute {
+ # rfc1738 says to use entity references here
+ local($_) = @_;
+ s/([\000-\031\"\'\`\%\&\<\>\177-\377])/sprintf('\&#%03d;',ord($1))/eg;
+ $_;
+}
+# encode unknown text data for using as HTML,
+# treats ^H as overstrike ala nroff.
+sub encode_data {
+ local($_) = @_;
+ local($str);
+
+ # Escape &, < and >
+ s,\010[><&],,g;
+ s/\&/\&amp\;/g;
+ s/\</\&lt\;/g;
+ s/\>/\&gt\;/g;
+
+ s,((_\010.)+),($str = $1) =~ s/.\010//g; "<I>$str</I>";,ge;
+ s,(.\010)+,$1,g;
+
+ if (!s,((.\010.)+\s+(.\010.)+),($str = $1) =~ s/.\010//g; "<B>$str</B>";,ge) {
+ s,((.\010.)+),($str = $1) =~ s/.\010//g; "<B>$str</B>";,ge;
+ }
+
+ s,.\010,,g;
+
+ $_;
+}
+
+sub html_header {
+ return qq{<HTML>
+<HEAD>
+<TITLE>$_[0]</TITLE>
+<link rev="made" href="mailto:wosch\@FreeBSD.ORG">
+<META name="robots" content="nofollow">
+<meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">
+<link rel="stylesheet" type="text/css" href="/swalter/style.css">
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" TEXT="#000000">\n\n};
+}
+
+sub mlnk {
+ local($matched) = @_;
+ return qq{<U>$matched</U>};
+}
+
+sub proc {
+ local(*FH, $prog, @args) = @_;
+ local($pid) = open(FH, "-|");
+ return undef unless defined($pid);
+ if ($pid == 0) {
+ exec $prog, @args;
+ &mydie("exec $prog failed\n");
+ }
+ 1;
+}
+
+# CGI script must die with error status 0
+sub mydie {
+ local($message) = @_;
+ print &html_header("Error");
+ print $message;
+
+print qq{
+<p>
+<A HREF="$BASE">Index Page and Help</A>
+</BODY>
+</HTML>
+};
+
+ exit(0);
+}
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__ */