From 92034c311a745284c6a5675fe42dc84af21bd2a6 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Sun, 2 Mar 2008 18:22:41 +0000 Subject: Initial import --- AUTHORS | 1 + COPYING | 38 ++ ChangeLog | 2 + Makefile.am | 6 + NEWS | 1 + README | 3 + autogen.sh | 11 + common/hash.c | 381 ++++++++++++++++++++ common/hash.h | 142 ++++++++ configure.in | 69 ++++ doc/BEGEMOT-MIB.txt | 59 ++++ doc/FOKUS-MIB.txt | 57 +++ doc/JAILS-MIB.txt | 118 +++++++ doc/Makefile.am | 12 + doc/bsnmp-jails.8 | 105 ++++++ doc/man2html.pl | 230 ++++++++++++ module/Makefile.am | 19 + module/bsnmp-jails.c | 947 ++++++++++++++++++++++++++++++++++++++++++++++++++ module/jails-tree.def | 64 ++++ module/usuals.h | 68 ++++ 20 files changed, 2333 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README create mode 100755 autogen.sh create mode 100644 common/hash.c create mode 100644 common/hash.h create mode 100644 configure.in create mode 100644 doc/BEGEMOT-MIB.txt create mode 100644 doc/FOKUS-MIB.txt create mode 100644 doc/JAILS-MIB.txt create mode 100644 doc/Makefile.am create mode 100644 doc/bsnmp-jails.8 create mode 100755 doc/man2html.pl create mode 100644 module/Makefile.am create mode 100644 module/bsnmp-jails.c create mode 100644 module/jails-tree.def create mode 100644 module/usuals.h diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..b122b64 --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Stef Walter 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: + 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 + */ + +/* 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 +#include +#include +#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 + * . + * + * 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 + */ + 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 + */ + +/* 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 + #if HAVE_NETINET_IN_H + #include + #endif + #if HAVE_NETINET_IN_SYSTM_H + #include + #endif + #if HAVE_NETINET_IP_H + #include + #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 +-- +-- 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 +-- +-- 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 +-- +-- 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 +.\" +.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 "

Man Page: ${title}

"; + print "
\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() {
+        # remove tailing white space
+        if (/^\s+$/) {
+            next if $space;
+            $space = 1;
+        } else {
+            $space = 0;
+        }
+
+        $_ = &encode_data($_);
+        if($enable_include_links &&
+           m,()?\#include()?\s+()?\<\;(.*\.h)\>\;()?,) {
+            $match = $4; ($regexp = $match) =~ s/\./\\\./;
+            s,$regexp,\$match\,;
+        }
+        /^\s/ &&                         # skip headers
+            s,((<[IB]>)?[\w\_\.\-]+\s*()?\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]+)/$1<\/A>/gi;
+        }
+
+        # detect URLs in manpages
+        if (m%tp://%) {
+            s,((ftp|http)://[^\s<>\)]+),$1,gi;
+        }
+
+        if (/^\S+/ && m%^([^<]+)%) {
+            $i = $1; $j = &encode_url($i);
+            s%^([^<]+)%$i%;
+            push(@sect, $1);
+        }
+        print;
+    }
+    close(MAN);
+
+    print "
   [ back | home ]
"; + print "\n"; + print "\n"; + + # Sleep 0.35 seconds to avoid DoS attacs + select undef, undef, undef, 0.35; +} + +# encode unknown data for use in ...</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] + + + + + +\n\n}; +} + +sub mlnk { + local($matched) = @_; + return qq{$matched}; +} + +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{ +

+Index Page and Help + + +}; + + 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 + */ + +#include "usuals.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#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 +# + +(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 + */ + +#ifndef __USUALS_H__ +#define __USUALS_H__ + +#include + +#include "config.h" + +#include +#include +#include +#include +#include + +#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__ */ -- cgit v1.2.3