diff options
| author | Stef Walter <stef@memberwebs.com> | 2008-03-02 18:22:41 +0000 | 
|---|---|---|
| committer | Stef Walter <stef@memberwebs.com> | 2008-03-02 18:22:41 +0000 | 
| commit | 92034c311a745284c6a5675fe42dc84af21bd2a6 (patch) | |
| tree | ff13e3f9c9ccb240618ff2075e3093d5bae127b5 | |
Initial import
| -rw-r--r-- | AUTHORS | 1 | ||||
| -rw-r--r-- | COPYING | 38 | ||||
| -rw-r--r-- | ChangeLog | 2 | ||||
| -rw-r--r-- | Makefile.am | 6 | ||||
| -rw-r--r-- | NEWS | 1 | ||||
| -rw-r--r-- | README | 3 | ||||
| -rwxr-xr-x | autogen.sh | 11 | ||||
| -rw-r--r-- | common/hash.c | 381 | ||||
| -rw-r--r-- | common/hash.h | 142 | ||||
| -rw-r--r-- | configure.in | 69 | ||||
| -rw-r--r-- | doc/BEGEMOT-MIB.txt | 59 | ||||
| -rw-r--r-- | doc/FOKUS-MIB.txt | 57 | ||||
| -rw-r--r-- | doc/JAILS-MIB.txt | 118 | ||||
| -rw-r--r-- | doc/Makefile.am | 12 | ||||
| -rw-r--r-- | doc/bsnmp-jails.8 | 105 | ||||
| -rwxr-xr-x | doc/man2html.pl | 230 | ||||
| -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 | 
20 files changed, 2333 insertions, 0 deletions
@@ -0,0 +1 @@ +Stef Walter <stef@memberwebs.com> @@ -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` + @@ -0,0 +1 @@ +See ChangeLog
\ No newline at end of file @@ -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>)?\<\;(.*\.h)\>\;(</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>   [ <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/\&/\&\;/g; +    s/\</\<\;/g; +    s/\>/\>\;/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__ */  | 
