Virgin import of bsnmp 1.4

This commit is contained in:
Hartmut Brandt 2003-11-10 08:53:38 +00:00
commit f06ca4af18
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/bsnmp/dist/; revision=122394
svn path=/vendor/bsnmp/1.4/; revision=122396; tag=vendor/bsnmp/1.4
50 changed files with 21792 additions and 0 deletions

43
contrib/bsnmp/NEWS Normal file
View File

@ -0,0 +1,43 @@
08-Nov-2003
WARNS=6 fixed.
28-Jan-2003
WARNS=5 fixes.
09-Jan-2003
snmpd: remove local socket in case of an error to fully initialize it.
Use chmod instead of fchmod. The latter seems not really to change
the mode of the socket.
lib: at program exit remove the local socket in the library.
11-Dec-2002
Implement listening on unix domain sockets. The client must bind
its socket, or the server cannot send back its response. These
sockets are considered to be more secure, because it is much
harder for an intruder to listen on them.
This requires changes in snmpmod.h and snmpclient.h.
04-Dec-2002
Sparc fixes.
15-Aug-2002
Use inttypes.h instead of limits.h to get integer limits. This
seems to be the Posix way.
First drafts of an snmpd, gensnmptree, asn1, bsnmplib,
bsnmpclient, bsnmpagent, snmpmod, snmp_mibII, snmp_netgraph man pages.
snmpd/main.c: reorder getopt options according to style(9). Implement
a -h option to print a short help.
25-Jun-2002
Makefiles rewritten to not use bsnmpmod.mk. The BSD makefiles are
really hard to use, because a) they are not documented and b) they
change much too often.
Make the patch a context diff instead of a unified one.
28-Feb-2002
Library code for SNMP clients.

65
contrib/bsnmp/README Normal file
View File

@ -0,0 +1,65 @@
Mon Nov 10 09:50:22 CET 2003
This is a mini-SNMP daemon. The basic daemon implements the system group
and a number of private extensions to manage the UDP transport mapping,
communities, trap destinations and loadable modules. In this form it can
be used to provide remote access to arbitrary data that can be described in
the form as required by the SMI. The daemon speaks both SNMPv1 and SNMPv2c.
One basic loadable module is provided together with the daemon:
- snmp_mibII provides the information groups for ip, tcp, and udp.
Installation
------------
You need to apply the patch in the patches directory to your system sources.
This adds a sysctl to retrieve multicast address information from the kernel.
As usual by doing:
make obj ; make depend ; make ; make install
This does not install a configuration file. The standard location for the
configuration is /etc/snmpd.config, but can be overwritten on the command
line. An example configuration file is provided.
Running
-------
snmpd [-m name[=value]] [-p pid-file] [-c config-file] [-d] [-l prefix]
[-D debug-flags] [-I path]
-m defines a configuration macro. If no value is given it
is set to the empty string.
-p specify the file where to store the PID. Default is
/var/run/{prefix}.pid.
-c specify the configuration file. Default is /etc/{prefix}.config.
-d don't go into daemon mode.
-l specify the prefix. This is used for the default config and
pid file names and for the syslog. Default is "snmpd".
-D specify debug flags:
d dump all PDUs.
e debug event library.
-I specify the include path for system configuration files.
Default is /etc:/usr/etc:/usr/local/etc.
The directory snmpd contains a snmpd.sh script, which can be copied to
/usr/local/etc/rc.d to automatically start and stop the daemon. snmpd.config
is an example config script.
Bug reports:
-----------
Please report bugs to harti@freebsd.org.
Happy hacking,
harti

5
contrib/bsnmp/TODO Normal file
View File

@ -0,0 +1,5 @@
snmpd_mibII:
- handle HC counters by periodically polling the kernel counters.
snmpd_netgraph:
- make some tables writeable

1
contrib/bsnmp/VERSION Normal file
View File

@ -0,0 +1 @@
1.4

View File

@ -0,0 +1,190 @@
.\"
.\" Copyright (c) 2001-2003
.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
.\" All rights reserved.
.\"
.\" Redistribution of this software and documentation 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 or documentation 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.
.\" 3. Neither the name of the Institute nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
.\" AND ITS 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
.\" FRAUNHOFER FOKUS OR ITS 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/gensnmptree/gensnmptree.1,v 1.1 2002/08/15 13:27:44 hbb Exp $
.\"
.\" Author: Harti Brandt <harti@freebsd.org>
.\"
.Dd October 7, 2003
.Dt gensnmptree 1
.Os
.Sh NAME
.Nm gensnmptree
.Nd "generate C and header files from a MIB description file"
.Sh SYNOPSIS
.Nm
.Op Fl hel
.Op Fl p Ar prefix
.Op Ar name Ar ...
.Sh DESCRIPTION
The
.Nm
utility is used to either generate C language tables and header files from
a MIB description or to numeric OIDs from MIB descriptions. The first form
is used only for maintaining the
.Xr snmpd 1
daemon or for module writers.
The second form may be used by SNMP client program writers.
.Pp
If the
.Fl e
option is not used
.Nm
reads a MIB description from its standard input and creates two files: a
C-file
.Ar prefix Ns tree.c
containing a table used by
.Xr snmpd 1
during PDU processing
and a header file
.Ar prefix Ns tree.h
containing appropriate declarations of the callback functions used in this table
and the table itself.
.Pp
If the
.Fl e
option is specified
.Nm
expects MIB variable names (only the last component) on its command line.
It reads a MIB specification from standard input and for each MIB variable
name emits two C preprocessor defines on its standard output. One define
.Va OID_ Ns Ar name
can be used as an array initialized to initialize a
.Va struct asn_oid .
The other define
.Va OIDLEN_ Ns Ar name
contains the length of the OID.
.Pp
The options are as follows:
.Bl -tag -width ".Fl d Ar argument"
.It Fl h
Print a short help page.
.It Fl e
Enter extract mode.
.It Fl l
Generate local preprocessor includes. This is used for bootstrapping
.Xr snmpd 1 .
.It Fl p Ar prefix
Prefix the file names and the table name with
.Ar prefix .
.El
.Sh MIBS
The syntax of the MIB description file can formally be specified as follows:
.Bd -unfilled -offset indent
tree := head elements ')'
entry := head ':' index STRING elements ')'
leaf := head TYPE STRING ACCESS ')'
column := head TYPE ACCESS ')'
head := '(' INT STRING
elements := EMPTY | elements element
element := tree | leaf
index := TYPE | index TYPE
.Ed
.Pp
.Ar TYPE
specifies a SNMP data type and may be one of
.Bl -bullet -offset indent -compact
.It
NULL
.It
INTEGER
.It
INTEGER32 (same as INTEGER)
.It
UNSIGNED32 (same as GAUGE)
.It
OCTETSTRING
.It
IPADDRESS
.It
OID
.It
TIMETICKS
.It
COUNTER
.It
GAUGE
.It
COUNTER64
.El
.Pp
.Ar ACCESS
specifies the accessibility of the MIB variable (which operation can be
performed) and is one of
.Bl -bullet -offset indent -compact
.It
GET
.It
SET
.El
.Pp
.Ar INT
is a decimal integer and
.Ar STRING
is any string starting with a letter or underscore and consisting of
letters, digits and underscores, that is not one of the keywords.
.Sh EXAMPLES
The following MIB description describes the system group:
.Bd -literal -offset indent
(1 internet
(2 mgmt
(1 mibII
(1 system
(1 sysDescr OCTETSTRING op_system_group GET)
(2 sysObjectId OID op_system_group GET)
(3 sysUpTime TIMETICKS op_system_group GET)
(4 sysContact OCTETSTRING op_system_group GET SET)
(5 sysName OCTETSTRING op_system_group GET SET)
(6 sysLocation OCTETSTRING op_system_group GET SET)
(7 sysServices INTEGER op_system_group GET)
(8 sysORLastChange TIMETICKS op_system_group GET)
(9 sysORTable
(1 sysOREntry : INTEGER op_or_table
(1 sysORIndex INTEGER)
(2 sysORID OID GET)
(3 sysORDescr OCTETSTRING GET)
(4 sysORUpTime TIMETICKS GET)
))
)
)
)
)
.Ed
.Sh SEE ALSO
.Xr snmpd 1
.Sh AUTHORS
.An Hartmut Brandt Aq harti@freebsd.org

View File

@ -0,0 +1,770 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/gensnmptree/gensnmptree.c,v 1.34 2003/01/28 13:44:34 hbb Exp $
*
* Generate OID table from table description.
*
* Syntax is:
* ---------
* tree := head elements ')'
*
* entry := head ':' index STRING elements ')'
*
* leaf := head TYPE STRING ACCESS ')'
*
* column := head TYPE ACCESS ')'
*
* head := '(' INT STRING
*
* elements := EMPTY | elements element
*
* element := tree | leaf
*
* index := TYPE | index TYPE
*
*/
#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <err.h>
#include <sys/queue.h>
#include "asn1.h"
#include "snmp.h"
#include "snmpagent.h"
/*
* Constant prefix for all OIDs
*/
static const asn_subid_t prefix[] = { 1, 3, 6 };
#define PREFIX_LEN (sizeof(prefix) / sizeof(prefix[0]))
u_int tree_size;
static const char *file_prefix = "";
static FILE *fp;
/* if true generate local include paths */
static int localincs = 0;
static const char usgtxt[] = "\
Generate SNMP tables. Copyright (c) 2001-2002 Fraunhofer Institute for\n\
Open Communication Systems (FhG Fokus). All rights reserved.\n\
usage: gensnmptree [-hel] [-p prefix] [name]...\n\
options:\n\
-h print this info\n\
-e extrace the named oids\n\
-l generate local include directives\n\
-p prefix prepend prefix to file and variable names\n\
";
/*
* A node in the OID tree
*/
enum ntype {
NODE_LEAF = 1,
NODE_TREE,
NODE_ENTRY,
NODE_COLUMN
};
enum {
FL_GET = 0x01,
FL_SET = 0x02,
};
struct node;
TAILQ_HEAD(node_list, node);
struct node {
enum ntype type;
asn_subid_t id; /* last element of OID */
char *name; /* name of node */
TAILQ_ENTRY(node) link;
u_int lno; /* starting line number */
u_int flags; /* allowed operations */
union {
struct tree {
struct node_list subs;
} tree;
struct entry {
u_int32_t index; /* index for table entry */
char *func; /* function for tables */
struct node_list subs;
} entry;
struct leaf {
enum snmp_syntax syntax; /* syntax for this leaf */
char *func; /* function name */
} leaf;
struct column {
enum snmp_syntax syntax; /* syntax for this column */
} column;
} u;
};
struct func {
const char *name;
LIST_ENTRY(func) link;
};
static LIST_HEAD(, func) funcs = LIST_HEAD_INITIALIZER(funcs);
/************************************************************
*
* Allocate memory and panic just in the case...
*/
static void *
xalloc(size_t size)
{
void *ptr;
if ((ptr = malloc(size)) == NULL)
err(1, "allocing %u bytes", size);
return (ptr);
}
/************************************************************
*
* Parsing input
*/
enum tok {
TOK_EOF = 0200, /* end-of-file seen */
TOK_NUM, /* number */
TOK_STR, /* string */
TOK_ACCESS, /* access operator */
TOK_TYPE, /* type operator */
};
static const struct {
const char *str;
enum tok tok;
u_int val;
} keywords[] = {
{ "GET", TOK_ACCESS, FL_GET },
{ "SET", TOK_ACCESS, FL_SET },
{ "NULL", TOK_TYPE, SNMP_SYNTAX_NULL },
{ "INTEGER", TOK_TYPE, SNMP_SYNTAX_INTEGER },
{ "INTEGER32", TOK_TYPE, SNMP_SYNTAX_INTEGER },
{ "UNSIGNED32", TOK_TYPE, SNMP_SYNTAX_GAUGE },
{ "OCTETSTRING", TOK_TYPE, SNMP_SYNTAX_OCTETSTRING },
{ "IPADDRESS", TOK_TYPE, SNMP_SYNTAX_IPADDRESS },
{ "OID", TOK_TYPE, SNMP_SYNTAX_OID },
{ "TIMETICKS", TOK_TYPE, SNMP_SYNTAX_TIMETICKS },
{ "COUNTER", TOK_TYPE, SNMP_SYNTAX_COUNTER },
{ "GAUGE", TOK_TYPE, SNMP_SYNTAX_GAUGE },
{ "COUNTER64", TOK_TYPE, SNMP_SYNTAX_COUNTER64 },
{ NULL, 0, 0 }
};
/* arbitrary upper limit on node names and function names */
#define MAXSTR 1000
char str[MAXSTR];
u_long val; /* integer values */
u_int lno = 1; /* current line number */
static void report(const char *, ...) __dead2 __printflike(1, 2);
static void report_node(const struct node *, const char *, ...)
__dead2 __printflike(2, 3);
/*
* Report an error and exit.
*/
static void
report(const char *fmt, ...)
{
va_list ap;
int c;
va_start(ap, fmt);
fprintf(stderr, "line %u: ", lno);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
fprintf(stderr, "context: \"");
while ((c = getchar()) != EOF && c != '\n')
fprintf(stderr, "%c", c);
fprintf(stderr, "\n");
va_end(ap);
exit(1);
}
static void
report_node(const struct node *np, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "line %u, node %s: ", np->lno, np->name);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
exit(1);
}
/*
* Return a fresh copy of the string constituting the current token.
*/
static char *
savetok(void)
{
return (strcpy(xalloc(strlen(str)+1), str));
}
/*
* Get the next token from input.
*/
static int
gettoken(void)
{
int c;
again:
/*
* Skip any whitespace before the next token
*/
while ((c = getchar()) != EOF) {
if (c == '\n')
lno++;
if (!isspace(c))
break;
}
if (c == EOF)
return (TOK_EOF);
if (!isascii(c))
report("unexpected character %#2x", (u_int)c);
/*
* Skip comments
*/
if (c == '#') {
while ((c = getchar()) != EOF) {
if (c == '\n') {
lno++;
goto again;
}
}
report("unexpected EOF in comment");
}
/*
* Single character tokens
*/
if (c == ')' || c == '(' || c == ':')
return (c);
/*
* Sort out numbers
*/
if (isdigit(c)) {
ungetc(c, stdin);
scanf("%lu", &val);
return (TOK_NUM);
}
/*
* So that has to be a string.
*/
if (isalpha(c) || c == '_') {
size_t n = 0;
str[n++] = c;
while ((c = getchar()) != EOF) {
if (!isalnum(c) && c != '_') {
ungetc(c, stdin);
break;
}
if (n == sizeof(str) - 1) {
str[n++] = '\0';
report("string too long '%s...'", str);
}
str[n++] = c;
}
str[n++] = '\0';
/*
* Keywords
*/
for (c = 0; keywords[c].str != NULL; c++)
if (strcmp(keywords[c].str, str) == 0) {
val = keywords[c].val;
return (keywords[c].tok);
}
return (TOK_STR);
}
if (isprint(c))
errx(1, "%u: unexpected character '%c'", lno, c);
else
errx(1, "%u: unexpected character 0x%02x", lno, (u_int)c);
}
/*
* Parse the next node (complete with all subnodes)
*/
static struct node *
parse(enum tok tok)
{
struct node *node;
struct node *sub;
u_int index_count;
node = xalloc(sizeof(struct node));
node->lno = lno;
if (tok != '(')
report("'(' expected at begin of node");
if (gettoken() != TOK_NUM)
report("node id expected after opening '('");
if (val > ASN_MAXID)
report("subid too large '%lu'", val);
node->id = (asn_subid_t)val;
if (gettoken() != TOK_STR)
report("node name expected after '(' ID");
node->name = savetok();
if ((tok = gettoken()) == TOK_TYPE) {
/* LEAF or COLUM */
u_int syntax = val;
if ((tok = gettoken()) == TOK_STR) {
/* LEAF */
node->type = NODE_LEAF;
node->u.leaf.func = savetok();
node->u.leaf.syntax = syntax;
tok = gettoken();
} else {
/* COLUMN */
node->type = NODE_COLUMN;
node->u.column.syntax = syntax;
}
while (tok != ')') {
if (tok != TOK_ACCESS)
report("access keyword or ')' expected");
node->flags |= (u_int)val;
tok = gettoken();
}
} else if (tok == ':') {
/* ENTRY */
node->type = NODE_ENTRY;
TAILQ_INIT(&node->u.entry.subs);
index_count = 0;
node->u.entry.index = 0;
while ((tok = gettoken()) == TOK_TYPE) {
if (index_count++ == SNMP_INDEXES_MAX)
report("too many table indexes");
node->u.entry.index |=
val << (SNMP_INDEX_SHIFT * index_count);
}
node->u.entry.index |= index_count;
if (index_count == 0)
report("need at least one index");
if (tok != TOK_STR)
report("function name expected");
node->u.entry.func = savetok();
tok = gettoken();
while (tok != ')') {
sub = parse(tok);
TAILQ_INSERT_TAIL(&node->u.entry.subs, sub, link);
tok = gettoken();
}
} else {
/* subtree */
node->type = NODE_TREE;
TAILQ_INIT(&node->u.tree.subs);
while (tok != ')') {
sub = parse(tok);
TAILQ_INSERT_TAIL(&node->u.tree.subs, sub, link);
tok = gettoken();
}
}
return (node);
}
/*
* Generate the C-code table part for one node.
*/
static void
gen_node(struct node *np, struct asn_oid *oid, u_int idx, const char *func)
{
u_int n;
struct node *sub;
u_int syntax;
if (oid->len == ASN_MAXOIDLEN)
report_node(np, "OID too long");
oid->subs[oid->len++] = np->id;
if (np->type == NODE_TREE) {
TAILQ_FOREACH(sub, &np->u.tree.subs, link)
gen_node(sub, oid, 0, NULL);
oid->len--;
return;
}
if (np->type == NODE_ENTRY) {
TAILQ_FOREACH(sub, &np->u.entry.subs, link)
gen_node(sub, oid, np->u.entry.index, np->u.entry.func);
oid->len--;
return;
}
/* leaf or column */
if ((np->flags & (FL_GET|FL_SET)) == 0) {
oid->len--;
return;
}
fprintf(fp, " {{ %u, {", oid->len);
for (n = 0; n < oid->len; n++)
fprintf(fp, " %u,", oid->subs[n]);
fprintf(fp, " }}, \"%s\", ", np->name);
if (np->type == NODE_COLUMN) {
syntax = np->u.column.syntax;
fprintf(fp, "SNMP_NODE_COLUMN, ");
} else {
syntax = np->u.leaf.syntax;
fprintf(fp, "SNMP_NODE_LEAF, ");
}
switch (syntax) {
case SNMP_SYNTAX_NULL:
fprintf(fp, "SNMP_SYNTAX_NULL, ");
break;
case SNMP_SYNTAX_INTEGER:
fprintf(fp, "SNMP_SYNTAX_INTEGER, ");
break;
case SNMP_SYNTAX_OCTETSTRING:
fprintf(fp, "SNMP_SYNTAX_OCTETSTRING, ");
break;
case SNMP_SYNTAX_IPADDRESS:
fprintf(fp, "SNMP_SYNTAX_IPADDRESS, ");
break;
case SNMP_SYNTAX_OID:
fprintf(fp, "SNMP_SYNTAX_OID, ");
break;
case SNMP_SYNTAX_TIMETICKS:
fprintf(fp, "SNMP_SYNTAX_TIMETICKS, ");
break;
case SNMP_SYNTAX_COUNTER:
fprintf(fp, "SNMP_SYNTAX_COUNTER, ");
break;
case SNMP_SYNTAX_GAUGE:
fprintf(fp, "SNMP_SYNTAX_GAUGE, ");
break;
case SNMP_SYNTAX_COUNTER64:
fprintf(fp, "SNMP_SYNTAX_COUNTER64, ");
break;
case SNMP_SYNTAX_NOSUCHOBJECT:
case SNMP_SYNTAX_NOSUCHINSTANCE:
case SNMP_SYNTAX_ENDOFMIBVIEW:
abort();
}
if (np->type == NODE_COLUMN)
fprintf(fp, "%s, ", func);
else
fprintf(fp, "%s, ", np->u.leaf.func);
fprintf(fp, "0");
if (np->flags & FL_SET)
fprintf(fp, "|SNMP_NODE_CANSET");
fprintf(fp, ", %#x, NULL },\n", idx);
oid->len--;
return;
}
/*
* Generate the header file with the function declarations.
*/
static void
gen_header(struct node *np, u_int oidlen, const char *func)
{
char f[MAXSTR + 4];
struct node *sub;
struct func *ptr;
oidlen++;
if (np->type == NODE_TREE) {
TAILQ_FOREACH(sub, &np->u.tree.subs, link)
gen_header(sub, oidlen, NULL);
return;
}
if (np->type == NODE_ENTRY) {
TAILQ_FOREACH(sub, &np->u.entry.subs, link)
gen_header(sub, oidlen, np->u.entry.func);
return;
}
if((np->flags & (FL_GET|FL_SET)) == 0)
return;
if (np->type == NODE_COLUMN)
sprintf(f, "%s", func);
else
sprintf(f, "%s", np->u.leaf.func);
LIST_FOREACH(ptr, &funcs, link)
if (strcmp(ptr->name, f) == 0)
break;
if (ptr == NULL) {
ptr = xalloc(sizeof(*ptr));
ptr->name = strcpy(xalloc(strlen(f)+1), f);
LIST_INSERT_HEAD(&funcs, ptr, link);
fprintf(fp, "int %s(struct snmp_context *, "
"struct snmp_value *, u_int, u_int, "
"enum snmp_op);\n", f);
}
fprintf(fp, "# define LEAF_%s %u\n", np->name, np->id);
}
/*
* Generate the OID table.
*/
static void
gen_table(struct node *node)
{
struct asn_oid oid;
fprintf(fp, "#include <sys/types.h>\n");
fprintf(fp, "#include <stdio.h>\n");
if (localincs) {
fprintf(fp, "#include \"asn1.h\"\n");
fprintf(fp, "#include \"snmp.h\"\n");
fprintf(fp, "#include \"snmpagent.h\"\n");
} else {
fprintf(fp, "#include <bsnmp/asn1.h>\n");
fprintf(fp, "#include <bsnmp/snmp.h>\n");
fprintf(fp, "#include <bsnmp/snmpagent.h>\n");
}
fprintf(fp, "#include \"%stree.h\"\n", file_prefix);
fprintf(fp, "\n");
fprintf(fp, "const struct snmp_node %sctree[] = {\n", file_prefix);
oid.len = PREFIX_LEN;
memcpy(oid.subs, prefix, sizeof(prefix));
gen_node(node, &oid, 0, NULL);
fprintf(fp, "};\n\n");
}
static int
extract(const struct node *np, struct asn_oid *oid, const char *obj)
{
struct node *sub;
u_long n;
if (oid->len == ASN_MAXOIDLEN)
report_node(np, "OID too long");
oid->subs[oid->len++] = np->id;
if (strcmp(obj, np->name) == 0) {
fprintf(fp, "#define OID_%s\t%u\n", np->name, np->id);
fprintf(fp, "#define OIDLEN_%s\t%u\n", np->name, oid->len);
fprintf(fp, "#define OIDX_%s\t{ %u, {", np->name, oid->len);
for (n = 0; n < oid->len; n++)
fprintf(fp, " %u,", oid->subs[n]);
fprintf(fp, " } }\n");
return (0);
}
if (np->type == NODE_TREE) {
TAILQ_FOREACH(sub, &np->u.tree.subs, link)
if (!extract(sub, oid, obj))
return (0);
} else if (np->type == NODE_ENTRY) {
TAILQ_FOREACH(sub, &np->u.entry.subs, link)
if (!extract(sub, oid, obj))
return (0);
}
oid->len--;
return (1);
}
static int
gen_extract(const struct node *root, const char *object)
{
struct asn_oid oid;
oid.len = PREFIX_LEN;
memcpy(oid.subs, prefix, sizeof(prefix));
return (extract(root, &oid, object));
}
static void
check_sub_order(const struct node *np, const struct node_list *subs)
{
int first;
const struct node *sub;
asn_subid_t maxid = 0;
/* ensure, that subids are ordered */
first = 1;
TAILQ_FOREACH(sub, subs, link) {
if (!first && sub->id <= maxid)
report_node(np, "subids not ordered at %s", sub->name);
maxid = sub->id;
first = 0;
}
}
/*
* Do some sanity checks on the tree definition and do some computations.
*/
static void
check_tree(struct node *np)
{
struct node *sub;
if (np->type == NODE_LEAF || np->type == NODE_COLUMN) {
if ((np->flags & (FL_GET|FL_SET)) != 0)
tree_size++;
return;
}
if (np->type == NODE_ENTRY) {
check_sub_order(np, &np->u.entry.subs);
/* ensure all subnodes are columns */
TAILQ_FOREACH(sub, &np->u.entry.subs, link) {
if (sub->type != NODE_COLUMN)
report_node(np, "entry subnode '%s' is not "
"a column", sub->name);
check_tree(sub);
}
} else {
check_sub_order(np, &np->u.tree.subs);
TAILQ_FOREACH(sub, &np->u.tree.subs, link)
check_tree(sub);
}
}
int
main(int argc, char *argv[])
{
int do_extract = 0;
int opt;
struct node *root;
char fname[MAXPATHLEN + 1];
while ((opt = getopt(argc, argv, "help:")) != EOF)
switch (opt) {
case 'h':
fprintf(stderr, "%s", usgtxt);
exit(0);
case 'e':
do_extract = 1;
break;
case 'l':
localincs = 1;
break;
case 'p':
file_prefix = optarg;
if (strlen(file_prefix) + strlen("tree.c") >
MAXPATHLEN)
errx(1, "prefix too long");
break;
}
if (!do_extract && argc != optind)
errx(1, "no arguments allowed");
if (do_extract && argc == optind)
errx(1, "no objects specified");
root = parse(gettoken());
if (gettoken() != TOK_EOF)
report("junk after closing ')'");
check_tree(root);
if (do_extract) {
fp = stdout;
while (optind < argc) {
if (gen_extract(root, argv[optind]))
errx(1, "object not found: %s", argv[optind]);
optind++;
}
return (0);
}
sprintf(fname, "%stree.h", file_prefix);
if ((fp = fopen(fname, "w")) == NULL)
err(1, "%s: ", fname);
gen_header(root, PREFIX_LEN, NULL);
fprintf(fp, "#define %sCTREE_SIZE %u\n", file_prefix, tree_size);
fprintf(fp, "extern const struct snmp_node %sctree[];\n", file_prefix);
fclose(fp);
sprintf(fname, "%stree.c", file_prefix);
if ((fp = fopen(fname, "w")) == NULL)
err(1, "%s: ", fname);
gen_table(root);
fclose(fp);
return (0);
}

484
contrib/bsnmp/lib/asn1.3 Normal file
View File

@ -0,0 +1,484 @@
.\"
.\" Copyright (c) 2001-2003
.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
.\" All rights reserved.
.\"
.\" Author: Harti Brandt <harti@freebsd.org>
.\"
.\" Redistribution of this software and documentation 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 or documentation 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.
.\" 3. Neither the name of the Institute nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
.\" AND ITS 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
.\" FRAUNHOFER FOKUS OR ITS 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/lib/asn1.3,v 1.2 2002/08/16 10:02:53 hbb Exp $
.\"
.Dd August 15, 2002
.Dt asn1 3
.Os
.Sh NAME
.Nm asn_get_header ,
.Nm asn_put_header ,
.Nm asn_put_temp_header ,
.Nm asn_commit_header ,
.Nm asn_get_integer_raw ,
.Nm asn_get_integer ,
.Nm asn_put_integer ,
.Nm asn_get_octetstring_raw ,
.Nm asn_get_octetstring ,
.Nm asn_put_octetstring ,
.Nm asn_get_null_raw ,
.Nm asn_get_null ,
.Nm asn_put_null ,
.Nm asn_put_exception ,
.Nm asn_get_objid_raw ,
.Nm asn_get_objid ,
.Nm asn_put_objid ,
.Nm asn_get_sequence ,
.Nm asn_get_ipaddress_raw ,
.Nm asn_get_ipaddress ,
.Nm asn_put_ipaddress ,
.Nm asn_get_uint32_raw ,
.Nm asn_put_uint32 ,
.Nm asn_get_counter64_raw ,
.Nm asn_put_counter64 ,
.Nm asn_get_timeticks ,
.Nm asn_put_timeticks ,
.Nm asn_skip ,
.Nm asn_slice_oid ,
.Nm asn_append_oid ,
.Nm asn_compare_oid ,
.Nm asn_is_suboid ,
.Nm asn_oid2str_r ,
.Nm asn_oid2str
.Nd "ASN.1 library for SNMP"
.Sh LIBRARY
Begemot SNMP library
.Pq libbsnmp, -lbsnmp
.Sh SYNOPSIS
.In bsnmp/asn1.h
.Ft enum asn_err
.Fn asn_get_header "struct asn_buf *buf" "u_char *type" "asn_len_t *lenp"
.Ft enum asn_err
.Fn asn_put_header "struct asn_buf *buf" "u_char type" "asn_len_t len"
.Ft enum asn_err
.Fn asn_put_temp_header "struct asn_buf *buf" "u_char type" "u_char **ptr"
.Ft enum asn_err
.Fn asn_commit_header "struct asn_buf *buf" "u_char *ptr"
.Ft enum asn_err
.Fn asn_get_integer_raw "struct asn_buf *buf" "asn_len_t len" "int32_t *res"
.Ft enum asn_err
.Fn asn_get_integer "struct asn_buf *buf" "int32_t *res"
.Ft enum asn_err
.Fn asn_put_integer "struct asn_buf *buf" "int32_t arg"
.Ft enum asn_err
.Fn asn_get_octetstring_raw "struct asn_buf *buf" "asn_len_t len" "u_char *out" "u_int *outsize"
.Ft enum asn_err
.Fn asn_get_octetstring "struct asn_buf *buf" "u_char *out" "u_int *outsize"
.Ft enum asn_err
.Fn asn_put_octetstring "struct asn_buf *buf" "const u_char *str" "u_int strsize"
.Ft enum asn_err
.Fn asn_get_null_raw "struct asn_buf *buf" "asn_len_t len"
.Ft enum asn_err
.Fn asn_get_null "struct asn_buf *buf"
.Ft enum asn_err
.Fn asn_put_null "struct asn_buf *buf"
.Ft enum asn_err
.Fn asn_put_exception "struct asn_buf *buf" "u_int type"
.Ft enum asn_err
.Fn asn_get_objid_raw "struct asn_buf *buf" "asn_len_t len" "struct asn_oid *oid"
.Ft enum asn_err
.Fn asn_get_objid "struct asn_buf *buf" "struct asn_oid *oid"
.Ft enum asn_err
.Fn asn_put_objid "struct asn_buf *buf" "const struct asn_oid *oid"
.Ft enum asn_err
.Fn asn_get_sequence "struct asn_buf *buf" "asn_len_t *lenp"
.Ft enum asn_err
.Fn asn_get_ipaddress_raw "struct asn_buf *buf" "asn_len_t len" "u_char *ipa"
.Ft enum asn_err
.Fn asn_get_ipaddress "struct asn_buf *buf" "u_char *ipa"
.Ft enum asn_err
.Fn asn_put_ipaddress "struct asn_buf *buf" "const u_char *ipa"
.Ft enum asn_err
.Fn asn_get_uint32_raw "struct asn_buf *buf" "asn_len_t len" "u_int32_t *res"
.Ft enum asn_err
.Fn asn_put_uint32 "struct asn_buf *buf" "u_char type" "u_int32_t val"
.Ft enum asn_err
.Fn asn_get_counter64_raw "struct asn_buf *buf" "asn_len_t len" "u_int64_t *res"
.Ft enum asn_err
.Fn asn_put_counter64 "struct asn_buf *buf" "u_int64_t val"
.Ft enum asn_err
.Fn asn_get_timeticks "struct asn_buf *buf" "u_int32_t *valp"
.Ft enum asn_err
.Fn asn_put_timeticks "struct asn_buf *buf" "u_int32_t val"
.Ft enum asn_err
.Fn asn_skip "struct asn_buf *buf" "asn_len_t len"
.Ft void
.Fn asn_slice_oid "struct asn_oid *dest" "const struct asn_oid *src" "u_int from" "u_int to"
.Ft void
.Fn asn_append_oid "struct asn_oid *to" "const struct asn_oid *from"
.Ft int
.Fn asn_compare_oid "const struct asn_oid *oid1" "const struct asn_oid *oid2"
.Ft int
.Fn asn_is_suboid "const struct asn_oid *oid1" "const struct asn_oid *oid2"
.Ft char *
.Fn asn_oid2str_r "const struct asn_oid *oid" "char *buf"
.Ft char *
.Fn asn_oid2str "const struct asn_oid *oid"
.Sh DESCRIPTION
The ASN.1 library contains routines to handle ASN.1 encoding for SNMP.
It supports only the restricted form of ASN.1 as required by SNMP. There
are two basic structures used throughout the library:
.Bd -literal -offset indent
/* these restrictions are in the SMI */
#define ASN_MAXID 0xffffffff
#define ASN_MAXOIDLEN 128
/* type of subidentifiers */
typedef u_int32_t asn_subid_t;
struct asn_oid {
u_int len;
asn_subid_t subs[ASN_MAXOIDLEN];
};
.Ed
.Pp
This structure represents an OID with the restrictions defined in the SNMP
SMI.
.Fa len
holds the current length of the OID and
.Fa subs
holds the elements of the OID.
.Bd -literal -offset indent
struct asn_buf {
union {
u_char *ptr;
const u_char *cptr;
} asn_u;
size_t asn_len;
};
#define asn_cptr asn_u.cptr
#define asn_ptr asn_u.ptr
.Ed
.Pp
This structure is used to encode and decode ASN.1. It describes the output
buffer for encoding routines and the input buffer for decoding routines.
For encoding
.Fa asn_len
holds the number of remaining free octets in the buffer. The first free byte
is pointed to by
.Fa asn_ptr .
For decoding
.Fa asn_len
holds the number of remaining bytes to decode. The next byte to decode is pointed
to by
.Fa asn_cptr .
.Pp
Most of the functions return an error code
.Fa "enum asn_error" :
.Bd -literal -offset indent
enum asn_err {
/* conversion was ok */
ASN_ERR_OK = 0,
/* conversion failed and stopped */
ASN_ERR_FAILED = 1 | 0x1000,
/* length field bad, value skipped */
ASN_ERR_BADLEN = 2,
/* out of buffer, stopped */
ASN_ERR_EOBUF = 3 | 0x1000,
/* length ok, but value is out of range */
ASN_ERR_RANGE = 4,
/* not the expected tag, stopped */
ASN_ERR_TAG = 5 | 0x1000,
};
#define ASN_ERR_STOPPED(E) (((E) & 0x1000) != 0)
.Ed
.Pp
If
.Fn ASN_ERR_STOPPED
returns true, the error was fatal and processing has stopped at the point
of error.
.Pp
The function
.Fn asn_get_header
reads the next header from the input octet stream. It returns the tag
in the variable pointed to by
.Fa type
(note that only single byte tags are supported) and the decoded length field
in the value pointed to by
.Fa lenp
(this is restricted to a unsigned 32-bit value). All errors in this function
are fatal and stop processing.
.Pp
The function
.Fn asn_put_header
writes an ASN.1 header.
.Fa type
is the tag to write and is restricted to one byte tags (i.e. tags
lesser or equal than 0x30).
.Fa len
is the length of the value and is restricted to 16-bit.
.Pp
The functions
.Fn asn_put_temp_header
and
.Fn asn_commit_header
are used to write a header when the length of the value is not known in
advance, for example, for sequences.
.Fn asn_put_temp_header
writes a header with the given tag
.Fa type
and space for the maximum supported length field and sets the pointer pointed
to by
.Fa ptr
to the begin of this length field. This pointer must then be fed into
.Fn asn_commit_header
directly after writing the value to the buffer. The function will compute the
length, insert it into the right place and shift the value if the resulting
length field is shorter than the estimated one.
.Pp
The function
.Fn asn_get_integer_raw
is used to decode a signed integer value (32-bit). It assumes, that the
header of the integer has been decoded already.
.Fa len
is the length obtained from the ASN.1 header and the integer will be returned
in the value pointed to by
.Fa res .
.Pp
The function
.Fn asn_get_integer
decodes a complete 32-bit signed integer including the header. If the
tag is wrong
.Li ASN_ERR_TAG
is returned.
The function
.Fn asn_put_integer
encodes a 32-bit signed integer.
.Pp
The function
.Fn asn_get_octetstring_raw
decodes the value field of an ASN.1 octet string. The length obtained from the
header must be fed into the
.Fa len
argument and
.Fa out
must point to a buffer to receive the octet string. On entry to the function
.Fa outsize
must point to the size of the buffer. On exit
.Fa outsize
will point to the number of octets decoded (if no error occurs this will be
equal to
.Fa len ).
The function
.Fn asn_get_octetstring
decodes an octetstring including the header.
.Fa out
must point to a buffer to receive the string,
.Fa outsize
must point to the size of the buffer. On exit of the function
.Fa outsize
will point to the number of octets decoded.
The function
.Fn asn_put_octetstring
encodes an octetstring (including the header).
.Fa str
points to the string to encode and
.Fa strsize
is the length of the string (the string may contain embedded
.Li NUL Ns s).
.Pp
The function
.Fn asn_get_null_raw
decodes a null value.
.Fa len
is the length obtained from the header and must be 0.
The function
.Fn asn_get_null
decodes a null including the header and the function
.Fn asn_put_null
encodes a null.
.Pp
The function
.Fn asn_put_exception
is used to encode an SNMPv2 exception. The exception type is
.Fa type .
.Pp
The function
.Fn asn_get_objid_raw
is used to decode an OID value.
.Fa len
must be the value length obtained from the header and
.Fa oid
will receive the decoded OID.
The function
.Fn asn_get_objid
decodes a complete OID (including the header) and the function
.Fn asn_put_objid
encodes a complete OID.
.Pp
The function
.Fn asn_get_sequence
decodes a sequence header.
The length of the sequence value will be stored in the value pointed to by
.Fa lenp .
.Pp
The function
.Fn asn_get_ipaddress_raw
decodes an IP address value.
.Fa len
is the length from the header and must be 4.
.Fa ipa
will receive the decoded IP address and must point to a buffer of at least
four bytes.
The function
.Fn asn_get_ipaddress
decodes a complete IP address (including the header) and
.Fn asn_put_ipaddress
encodes an IP address.
.Pp
The function
.Fn asn_get_uint32_raw
decodes an unsigned 32-bit integer value.
.Fa len
is the length from the header and
.Fa res
will get the decoded value.
The function
.Fn asn_put_uint32
encodes an unsigned 32-bit integer value and inserts the tag given in
.Fa type
into the header.
.Pp
The function
.Fn asn_get_counter64_raw
decodes an unsigned 64-bit integer value.
.Fa len
must be the value length from the header. The resulting value is
stored into the variable pointed to by
.Fa res .
The function
.Fn asn_put_counter64
encodes a complete unsigned 64-bit value.
.Pp
The function
.Fn asn_get_timeticks
decodes an ASN.1 object of type
.Li TIMETICKS
and the function
.Fn asn_put_timeticks
encodes such an object.
.Pp
The function
.Fn asn_skip
can be used to skip
.Fa len
bytes in the input buffer.
.Pp
The function
.Fn asn_slice_oid
splits a part out from an OID. It takes all the subids from the OID
pointed to by
.Fa src
starting with the subid at position
.Fa from
(the first subid beeing subid 0) up to, but not including, subid
.Fa to
and generates a new OID in
.Fa dest .
If
.Fa to
is less or equal to
.Fa from
the resulting OID will have a length of zero.
.Pp
The function
.Fn asn_append_oid
appends the OID
.Fa from
to the OID
.Fa to
given that the resulting OID is not too long. If the maximum length is exceeded
the result is undefined.
.Pp
The function
.Fn asn_compare_oid
compares two oids and returns the values
.Li -1 ,
.Li 0 or
.Li +1
when
.Fa oid1
is lesser than, equal, or larger than
.Fa oid2
resp.
.Pp
The function
.Fn asn_is_suboid
returns 1 if
.Fa oid1
is equal to the leading part of
.Fa oid2 .
It returns 0 otherwise.
.Pp
The function
.Fn asn_oid2str_r
makes a printable string from
.Fa oid .
The buffer pointed to by
.Fa str
must be large enough to hold the result. The constant
.Li ASN_OIDSTRLEN
is defined to be the length of the maximum string generated by this function
(including the trailing NUL).
The function
.Fn asn_oid2str
makes a printable string from
.Fa oid
into a private buffer that is overwritten by each call.
.Sh DIAGNOSTICS
When an error occures in any of the function the function pointed to
by the global pointer
.Bd -literal -offset indent
extern void (*asn_error)(const struct asn_buf *, const char *, ...);
.Ed
.Pp
is called with the current buffer (this may be
.Li NULL )
and a
.Xr printf 3
style format string.
There is a default error handler in the library that prints a message
starting with
.Sq ASN.1:
followed by the error message and an optional dump of the buffer.
.Sh SEE ALSO
.Xr snmpd 1 ,
.Xr gensnmptree 1 ,
.Xr bsnmplib 3
.Xr bsnmpclient 3 ,
.Xr bsnmpagent 3
.Sh STANDARDS
This implementation conforms to the applicable IETF RFCs and ITU-T
recommendations.
.Sh AUTHORS
.An Hartmut Brandt Aq brandt@fokus.gmd.de

994
contrib/bsnmp/lib/asn1.c Normal file
View File

@ -0,0 +1,994 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/lib/asn1.c,v 1.24 2003/01/28 13:44:34 hbb Exp $
*
* ASN.1 for SNMP.
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <inttypes.h>
#include <assert.h>
#include "asn1.h"
static void asn_error_func(const struct asn_buf *, const char *, ...);
void (*asn_error)(const struct asn_buf *, const char *, ...) = asn_error_func;
/*
* Read the next header. This reads the tag (note, that only single
* byte tags are supported for now) and the length field. The length field
* is restricted to a 32-bit value.
* All errors of this function stop the decoding.
*/
enum asn_err
asn_get_header(struct asn_buf *b, u_char *type, asn_len_t *len)
{
u_int length;
if (b->asn_len == 0) {
asn_error(b, "no identifier for header");
return (ASN_ERR_EOBUF);
}
*type = *b->asn_cptr;
if ((*type & ASN_TYPE_MASK) > 0x30) {
asn_error(b, "types > 0x30 not supported (%u)",
*type & ASN_TYPE_MASK);
return (ASN_ERR_FAILED);
}
b->asn_cptr++;
b->asn_len--;
if (b->asn_len == 0) {
asn_error(b, "no length field");
return (ASN_ERR_EOBUF);
}
if (*b->asn_cptr & 0x80) {
length = *b->asn_cptr++ & 0x7f;
b->asn_len--;
if (length == 0) {
asn_error(b, "indefinite length not supported");
return (ASN_ERR_FAILED);
}
if (length > ASN_MAXLENLEN) {
asn_error(b, "long length too long (%u)", length);
return (ASN_ERR_FAILED);
}
if (length > b->asn_len) {
asn_error(b, "long length truncated");
return (ASN_ERR_EOBUF);
}
*len = 0;
while (length--) {
*len = (*len << 8) | *b->asn_cptr++;
b->asn_len--;
}
} else {
*len = *b->asn_cptr++;
b->asn_len--;
}
return (ASN_ERR_OK);
}
/*
* Write a length field (restricted to values < 2^32-1) and return the
* number of bytes this field takes. If ptr is NULL, the length is computed
* but nothing is written. If the length would be too large return 0.
*/
static u_int
asn_put_len(u_char *ptr, asn_len_t len)
{
u_int lenlen, lenlen1;
asn_len_t tmp;
if (len > ASN_MAXLEN) {
asn_error(NULL, "encoding length too long: (%u)", len);
return (0);
}
if (len <= 127) {
if (ptr)
*ptr++ = (u_char)len;
return (1);
} else {
lenlen = 0;
/* compute number of bytes for value (is at least 1) */
for (tmp = len; tmp != 0; tmp >>= 8)
lenlen++;
if (ptr != NULL) {
*ptr++ = (u_char)lenlen | 0x80;
lenlen1 = lenlen;
while (lenlen1-- > 0) {
ptr[lenlen1] = len & 0xff;
len >>= 8;
}
}
return (lenlen + 1);
}
}
/*
* Write a header (tag and length fields).
* Tags are restricted to one byte tags (value <= 0x30) and the
* lenght field to 16-bit. All errors stop the encoding.
*/
enum asn_err
asn_put_header(struct asn_buf *b, u_char type, asn_len_t len)
{
u_int lenlen;
/* tag field */
if ((type & ASN_TYPE_MASK) > 0x30) {
asn_error(NULL, "types > 0x30 not supported (%u)",
type & ASN_TYPE_MASK);
return (ASN_ERR_FAILED);
}
if (b->asn_len == 0)
return (ASN_ERR_EOBUF);
*b->asn_ptr++ = type;
b->asn_len--;
/* length field */
if ((lenlen = asn_put_len(NULL, len)) == 0)
return (ASN_ERR_FAILED);
if (b->asn_len < lenlen)
return (ASN_ERR_EOBUF);
(void)asn_put_len(b->asn_ptr, len);
b->asn_ptr += lenlen;
b->asn_len -= lenlen;
return (ASN_ERR_OK);
}
/*
* This constructs a temporary sequence header with space for the maximum
* length field (three byte). Set the pointer that ptr points to to the
* start of the encoded header. This is used for a later call to
* asn_commit_header which will fix-up the length field and move the
* value if needed. All errors should stop the encoding.
*/
#define TEMP_LEN (1 + ASN_MAXLENLEN + 1)
enum asn_err
asn_put_temp_header(struct asn_buf *b, u_char type, u_char **ptr)
{
int ret;
if (b->asn_len < TEMP_LEN)
return (ASN_ERR_EOBUF);
*ptr = b->asn_ptr;
if ((ret = asn_put_header(b, type, ASN_MAXLEN)) == ASN_ERR_OK)
assert(b->asn_ptr == *ptr + TEMP_LEN);
return (ret);
}
enum asn_err
asn_commit_header(struct asn_buf *b, u_char *ptr)
{
asn_len_t len;
u_int lenlen, shift;
/* compute length of encoded value without header */
len = b->asn_ptr - (ptr + TEMP_LEN);
/* insert length. may not fail. */
lenlen = asn_put_len(ptr + 1, len);
if (lenlen > TEMP_LEN - 1)
return (ASN_ERR_FAILED);
if (lenlen < TEMP_LEN - 1) {
/* shift value down */
shift = (TEMP_LEN - 1) - lenlen;
memmove(ptr + 1 + lenlen, ptr + TEMP_LEN, len);
b->asn_ptr -= shift;
b->asn_len += shift;
}
return (ASN_ERR_OK);
}
#undef TEMP_LEN
/*
* BER integer. This may be used to get a signed 64 bit integer at maximum.
* The maximum length should be checked by the caller. This cannot overflow
* if the caller ensures that len is at maximum 8.
*
* <bytes>
*/
static enum asn_err
asn_get_real_integer(struct asn_buf *b, asn_len_t len, int64_t *vp)
{
u_int64_t val;
int neg = 0;
enum asn_err err;
if (b->asn_len < len) {
asn_error(b, "truncated integer");
return (ASN_ERR_EOBUF);
}
if (len == 0) {
asn_error(b, "zero-length integer");
*vp = 0;
return (ASN_ERR_BADLEN);
}
err = ASN_ERR_OK;
if (len > 8)
err = ASN_ERR_RANGE;
if (*b->asn_cptr & 0x80)
neg = 1;
val = 0;
while (len--) {
val <<= 8;
val |= neg ? (u_char)~*b->asn_cptr : *b->asn_cptr;
b->asn_len--;
b->asn_cptr++;
}
if (neg) {
*vp = -(int64_t)val - 1;
} else
*vp = (int64_t)val;
return (err);
}
/*
* Write a signed integer with the given type. The caller has to ensure
* that the actual value is ok for this type.
*/
static enum asn_err
asn_put_real_integer(struct asn_buf *b, u_char type, int64_t ival)
{
int i, neg = 0;
# define OCTETS 8
u_char buf[OCTETS];
u_int64_t val;
enum asn_err ret;
if (ival < 0) {
/* this may fail if |INT64_MIN| > |INT64_MAX| and
* the value is between * INT64_MIN <= ival < -(INT64_MAX+1) */
val = (u_int64_t)-(ival + 1);
neg = 1;
} else
val = (u_int64_t)ival;
/* split the value into octets */
for (i = OCTETS - 1; i >= 0; i--) {
buf[i] = val & 0xff;
if (neg)
buf[i] = ~buf[i];
val >>= 8;
}
/* no leading 9 zeroes or ones */
for (i = 0; i < OCTETS - 1; i++)
if (!((buf[i] == 0xff && (buf[i + 1] & 0x80) != 0) ||
(buf[i] == 0x00 && (buf[i + 1] & 0x80) == 0)))
break;
if ((ret = asn_put_header(b, type, OCTETS - i)))
return (ret);
if (OCTETS - (u_int)i > b->asn_len)
return (ASN_ERR_EOBUF);
while (i < OCTETS) {
*b->asn_ptr++ = buf[i++];
b->asn_len--;
}
return (ASN_ERR_OK);
# undef OCTETS
}
/*
* The same for unsigned 64-bitters. Here we have the problem, that overflow
* can happen, because the value maybe 9 bytes long. In this case the
* first byte must be 0.
*/
static enum asn_err
asn_get_real_unsigned(struct asn_buf *b, asn_len_t len, u_int64_t *vp)
{
enum asn_err err;
if (b->asn_len < len) {
asn_error(b, "truncated integer");
return (ASN_ERR_EOBUF);
}
if (len == 0) {
asn_error(b, "zero-length integer");
*vp = 0;
return (ASN_ERR_BADLEN);
}
err = ASN_ERR_OK;
*vp = 0;
if ((*b->asn_cptr & 0x80) || (len == 9 && *b->asn_cptr != 0)) {
/* negative integer or too larger */
*vp = 0xffffffffffffffffULL;
err = ASN_ERR_RANGE;
}
while (len--) {
*vp = (*vp << 8) | *b->asn_cptr++;
b->asn_len--;
}
return (err);
}
/*
* Values with the msb on need 9 octets.
*/
static int
asn_put_real_unsigned(struct asn_buf *b, u_char type, u_int64_t val)
{
int i;
# define OCTETS 9
u_char buf[OCTETS];
enum asn_err ret;
/* split the value into octets */
for (i = OCTETS - 1; i >= 0; i--) {
buf[i] = val & 0xff;
val >>= 8;
}
/* no leading 9 zeroes */
for (i = 0; i < OCTETS - 1; i++)
if (!(buf[i] == 0x00 && (buf[i + 1] & 0x80) == 0))
break;
if ((ret = asn_put_header(b, type, OCTETS - i)))
return (ret);
if (OCTETS - (u_int)i > b->asn_len)
return (ASN_ERR_EOBUF);
while (i < OCTETS) {
*b->asn_ptr++ = buf[i++];
b->asn_len--;
}
#undef OCTETS
return (ASN_ERR_OK);
}
/*
* The ASN.1 INTEGER type is restricted to 32-bit signed by the SMI.
*/
enum asn_err
asn_get_integer_raw(struct asn_buf *b, asn_len_t len, int32_t *vp)
{
int64_t val;
enum asn_err ret;
if ((ret = asn_get_real_integer(b, len, &val)) == ASN_ERR_OK) {
if (len > 4)
ret = ASN_ERR_BADLEN;
else if (val > INT32_MAX || val < INT32_MIN)
/* may not happen */
ret = ASN_ERR_RANGE;
*vp = (int32_t)val;
}
return (ret);
}
enum asn_err
asn_get_integer(struct asn_buf *b, int32_t *vp)
{
asn_len_t len;
u_char type;
enum asn_err err;
if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
return (err);
if (type != ASN_TYPE_INTEGER) {
asn_error(b, "bad type for integer (%u)", type);
return (ASN_ERR_TAG);
}
return (asn_get_integer_raw(b, len, vp));
}
enum asn_err
asn_put_integer(struct asn_buf *b, int32_t val)
{
return (asn_put_real_integer(b, ASN_TYPE_INTEGER, val));
}
/*
* OCTETSTRING
*
* <0x04> <len> <data ...>
*
* Get an octetstring. noctets must point to the buffer size and on
* return will contain the size of the octetstring, regardless of the
* buffer size.
*/
enum asn_err
asn_get_octetstring_raw(struct asn_buf *b, asn_len_t len, u_char *octets,
u_int *noctets)
{
enum asn_err err = ASN_ERR_OK;
if (*noctets < len) {
asn_error(b, "octetstring truncated");
err = ASN_ERR_RANGE;
}
if (b->asn_len < len) {
asn_error(b, "truncatet octetstring");
return (ASN_ERR_EOBUF);
}
if (*noctets < len)
memcpy(octets, b->asn_cptr, *noctets);
else
memcpy(octets, b->asn_cptr, len);
*noctets = len;
b->asn_cptr += len;
b->asn_len -= len;
return (err);
}
enum asn_err
asn_get_octetstring(struct asn_buf *b, u_char *octets, u_int *noctets)
{
enum asn_err err;
u_char type;
asn_len_t len;
if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
return (err);
if (type != ASN_TYPE_OCTETSTRING) {
asn_error(b, "bad type for octetstring (%u)", type);
return (ASN_ERR_TAG);
}
return (asn_get_octetstring_raw(b, len, octets, noctets));
}
enum asn_err
asn_put_octetstring(struct asn_buf *b, const u_char *octets, u_int noctets)
{
enum asn_err ret;
if ((ret = asn_put_header(b, ASN_TYPE_OCTETSTRING, noctets)) != ASN_ERR_OK)
return (ret);
if (b->asn_len < noctets)
return (ASN_ERR_EOBUF);
memcpy(b->asn_ptr, octets, noctets);
b->asn_ptr += noctets;
b->asn_len -= noctets;
return (ASN_ERR_OK);
}
/*
* NULL
*
* <0x05> <0x00>
*/
enum asn_err
asn_get_null_raw(struct asn_buf *b, asn_len_t len)
{
if (len != 0) {
if (b->asn_len < len) {
asn_error(b, "truncated NULL");
return (ASN_ERR_EOBUF);
}
asn_error(b, "bad length for NULL (%u)", len);
b->asn_len -= len;
b->asn_ptr += len;
return (ASN_ERR_BADLEN);
}
return (ASN_ERR_OK);
}
enum asn_err
asn_get_null(struct asn_buf *b)
{
u_char type;
asn_len_t len;
enum asn_err err;
if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
return (err);
if (type != ASN_TYPE_NULL) {
asn_error(b, "bad type for NULL (%u)", type);
return (ASN_ERR_TAG);
}
return (asn_get_null_raw(b, len));
}
enum asn_err
asn_put_null(struct asn_buf *b)
{
return (asn_put_header(b, ASN_TYPE_NULL, 0));
}
enum asn_err
asn_put_exception(struct asn_buf *b, u_int except)
{
return (asn_put_header(b, ASN_CLASS_CONTEXT | except, 0));
}
/*
* OBJID
*
* <0x06> <len> <subid...>
*/
enum asn_err
asn_get_objid_raw(struct asn_buf *b, asn_len_t len, struct asn_oid *oid)
{
asn_subid_t subid;
enum asn_err err;
if (b->asn_len < len) {
asn_error(b, "truncated OBJID");
return (ASN_ERR_EOBUF);
}
oid->len = 0;
if (len == 0) {
asn_error(b, "short OBJID");
oid->subs[oid->len++] = 0;
oid->subs[oid->len++] = 0;
return (ASN_ERR_BADLEN);
}
err = ASN_ERR_OK;
while (len != 0) {
if (oid->len == ASN_MAXOIDLEN) {
asn_error(b, "OID too long (%u)", oid->len);
b->asn_cptr += len;
b->asn_len -= len;
return (ASN_ERR_BADLEN);
}
subid = 0;
do {
if (len == 0) {
asn_error(b, "unterminated subid");
return (ASN_ERR_EOBUF);
}
if (subid > (ASN_MAXID >> 7)) {
asn_error(b, "OBID subid too larger");
err = ASN_ERR_RANGE;
}
subid = (subid << 7) | (*b->asn_cptr & 0x7f);
len--;
b->asn_len--;
} while (*b->asn_cptr++ & 0x80);
if (oid->len == 0) {
if (subid < 80) {
oid->subs[oid->len++] = subid / 40;
oid->subs[oid->len++] = subid % 40;
} else {
oid->subs[oid->len++] = 2;
oid->subs[oid->len++] = subid - 80;
}
} else {
oid->subs[oid->len++] = subid;
}
}
return (err);
}
enum asn_err
asn_get_objid(struct asn_buf *b, struct asn_oid *oid)
{
u_char type;
asn_len_t len;
enum asn_err err;
if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
return (err);
if (type != ASN_TYPE_OBJID) {
asn_error(b, "bad type for OBJID (%u)", type);
return (ASN_ERR_TAG);
}
return (asn_get_objid_raw(b, len, oid));
}
enum asn_err
asn_put_objid(struct asn_buf *b, const struct asn_oid *oid)
{
asn_subid_t first, sub;
enum asn_err err, err1;
u_int i, oidlen;
asn_len_t len;
err = ASN_ERR_OK;
if (oid->len == 0) {
/* illegal */
asn_error(NULL, "short oid");
err = ASN_ERR_RANGE;
first = 0;
oidlen = 2;
} else if (oid->len == 1) {
/* illegal */
asn_error(b, "short oid");
if (oid->subs[0] > 2)
asn_error(NULL, "oid[0] too large (%u)", oid->subs[0]);
err = ASN_ERR_RANGE;
first = oid->subs[0] * 40;
oidlen = 2;
} else {
if (oid->len > ASN_MAXOIDLEN) {
asn_error(NULL, "oid too long %u", oid->len);
err = ASN_ERR_RANGE;
}
if (oid->subs[0] > 2 ||
(oid->subs[0] < 2 && oid->subs[0] >= 40)) {
asn_error(NULL, "oid out of range (%u,%u)",
oid->subs[0], oid->subs[1]);
err = ASN_ERR_RANGE;
}
first = 40 * oid->subs[0] + oid->subs[1];
oidlen = oid->len;
}
len = 0;
for (i = 1; i < oidlen; i++) {
sub = (i == 1) ? first : oid->subs[i];
if (sub > ASN_MAXID) {
asn_error(NULL, "oid subid too large");
err = ASN_ERR_RANGE;
}
len += (sub <= 0x7f) ? 1
: (sub <= 0x3fff) ? 2
: (sub <= 0x1fffff) ? 3
: (sub <= 0xfffffff) ? 4
: 5;
}
if ((err1 = asn_put_header(b, ASN_TYPE_OBJID, len)) != ASN_ERR_OK)
return (err1);
if (b->asn_len < len)
return (ASN_ERR_EOBUF);
for (i = 1; i < oidlen; i++) {
sub = (i == 1) ? first : oid->subs[i];
if (sub <= 0x7f) {
*b->asn_ptr++ = sub;
b->asn_len--;
} else if (sub <= 0x3fff) {
*b->asn_ptr++ = (sub >> 7) | 0x80;
*b->asn_ptr++ = sub & 0x7f;
b->asn_len -= 2;
} else if (sub <= 0x1fffff) {
*b->asn_ptr++ = (sub >> 14) | 0x80;
*b->asn_ptr++ = ((sub >> 7) & 0x7f) | 0x80;
*b->asn_ptr++ = sub & 0x7f;
b->asn_len -= 3;
} else if (sub <= 0xfffffff) {
*b->asn_ptr++ = (sub >> 21) | 0x80;
*b->asn_ptr++ = ((sub >> 14) & 0x7f) | 0x80;
*b->asn_ptr++ = ((sub >> 7) & 0x7f) | 0x80;
*b->asn_ptr++ = sub & 0x7f;
b->asn_len -= 4;
} else {
*b->asn_ptr++ = (sub >> 28) | 0x80;
*b->asn_ptr++ = ((sub >> 21) & 0x7f) | 0x80;
*b->asn_ptr++ = ((sub >> 14) & 0x7f) | 0x80;
*b->asn_ptr++ = ((sub >> 7) & 0x7f) | 0x80;
*b->asn_ptr++ = sub & 0x7f;
b->asn_len -= 5;
}
}
return (err);
}
/*
* SEQUENCE header
*
* <0x10|0x20> <len> <data...>
*/
enum asn_err
asn_get_sequence(struct asn_buf *b, asn_len_t *len)
{
u_char type;
enum asn_err err;
if ((err = asn_get_header(b, &type, len)) != ASN_ERR_OK)
return (err);
if (type != (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED)) {
asn_error(b, "bad sequence type %u", type);
return (ASN_ERR_TAG);
}
if (*len > b->asn_len) {
asn_error(b, "truncated sequence");
return (ASN_ERR_EOBUF);
}
return (ASN_ERR_OK);
}
/*
* Application types
*
* 0x40 4 MSB 2MSB 2LSB LSB
*/
enum asn_err
asn_get_ipaddress_raw(struct asn_buf *b, asn_len_t len, u_char *addr)
{
u_int i;
if (b->asn_len < len) {
asn_error(b, "truncated ip-address");
return (ASN_ERR_EOBUF);
}
if (len < 4) {
asn_error(b, "short length for ip-Address %u", len);
for (i = 0; i < len; i++)
*addr++ = *b->asn_cptr++;
while (i++ < len)
*addr++ = 0;
b->asn_len -= len;
return (ASN_ERR_BADLEN);
}
for (i = 0; i < 4; i++)
*addr++ = *b->asn_cptr++;
b->asn_cptr += len - 4;
b->asn_len -= len;
return (ASN_ERR_OK);
}
enum asn_err
asn_get_ipaddress(struct asn_buf *b, u_char *addr)
{
u_char type;
asn_len_t len;
enum asn_err err;
if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
return (err);
if (type != (ASN_CLASS_APPLICATION|ASN_APP_IPADDRESS)) {
asn_error(b, "bad type for ip-address %u", type);
return (ASN_ERR_TAG);
}
return (asn_get_ipaddress_raw(b, len, addr));
}
enum asn_err
asn_put_ipaddress(struct asn_buf *b, const u_char *addr)
{
enum asn_err err;
if ((err = asn_put_header(b, ASN_CLASS_APPLICATION|ASN_APP_IPADDRESS,
4)) != ASN_ERR_OK)
return (err);
if (b->asn_len < 4)
return (ASN_ERR_EOBUF);
memcpy(b->asn_ptr, addr, 4);
b->asn_ptr += 4;
b->asn_len -= 4;
return (ASN_ERR_OK);
}
/*
* UNSIGNED32
*
* 0x42|0x41 <len> ...
*/
enum asn_err
asn_get_uint32_raw(struct asn_buf *b, asn_len_t len, u_int32_t *vp)
{
u_int64_t v;
enum asn_err err;
if ((err = asn_get_real_unsigned(b, len, &v)) == ASN_ERR_OK) {
if (len > 5) {
asn_error(b, "uint32 too long %u", len);
err = ASN_ERR_BADLEN;
} else if (v > UINT32_MAX) {
asn_error(b, "uint32 too large %llu", v);
err = ASN_ERR_RANGE;
}
*vp = (u_int32_t)v;
}
return (err);
}
enum asn_err
asn_put_uint32(struct asn_buf *b, u_char type, u_int32_t val)
{
u_int64_t v = val;
return (asn_put_real_unsigned(b, ASN_CLASS_APPLICATION|type, v));
}
/*
* COUNTER64
* 0x46 <len> ...
*/
enum asn_err
asn_get_counter64_raw(struct asn_buf *b, asn_len_t len, u_int64_t *vp)
{
return (asn_get_real_unsigned(b, len, vp));
}
enum asn_err
asn_put_counter64(struct asn_buf *b, u_int64_t val)
{
return (asn_put_real_unsigned(b,
ASN_CLASS_APPLICATION | ASN_APP_COUNTER64, val));
}
/*
* TimeTicks
* 0x43 <len> ...
*/
enum asn_err
asn_get_timeticks(struct asn_buf *b, u_int32_t *vp)
{
asn_len_t len;
u_char type;
enum asn_err err;
if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
return (err);
if (type != (ASN_CLASS_APPLICATION|ASN_APP_TIMETICKS)) {
asn_error(b, "bad type for timeticks %u", type);
return (ASN_ERR_TAG);
}
return (asn_get_uint32_raw(b, len, vp));
}
enum asn_err
asn_put_timeticks(struct asn_buf *b, u_int32_t val)
{
u_int64_t v = val;
return (asn_put_real_unsigned(b,
ASN_CLASS_APPLICATION | ASN_APP_TIMETICKS, v));
}
/*
* Construct a new OID by taking a range of sub ids of the original oid.
*/
void
asn_slice_oid(struct asn_oid *dest, const struct asn_oid *src,
u_int from, u_int to)
{
if (from >= to) {
dest->len = 0;
return;
}
dest->len = to - from;
memcpy(dest->subs, &src->subs[from], dest->len * sizeof(dest->subs[0]));
}
/*
* Append from to to
*/
void
asn_append_oid(struct asn_oid *to, const struct asn_oid *from)
{
memcpy(&to->subs[to->len], &from->subs[0],
from->len * sizeof(from->subs[0]));
to->len += from->len;
}
/*
* Skip a value
*/
enum asn_err
asn_skip(struct asn_buf *b, asn_len_t len)
{
if (b->asn_len < len)
return (ASN_ERR_EOBUF);
b->asn_cptr += len;
b->asn_len -= len;
return (ASN_ERR_OK);
}
/*
* Compare two OIDs.
*
* o1 < o2 : -1
* o1 > o2 : +1
* o1 = o2 : 0
*/
int
asn_compare_oid(const struct asn_oid *o1, const struct asn_oid *o2)
{
u_long i;
for (i = 0; i < o1->len && i < o2->len; i++) {
if (o1->subs[i] < o2->subs[i])
return (-1);
if (o1->subs[i] > o2->subs[i])
return (+1);
}
if (o1->len < o2->len)
return (-1);
if (o1->len > o2->len)
return (+1);
return (0);
}
/*
* Check whether an OID is a sub-string of another OID.
*/
int
asn_is_suboid(const struct asn_oid *o1, const struct asn_oid *o2)
{
u_long i;
for (i = 0; i < o1->len; i++)
if (i >= o2->len || o1->subs[i] != o2->subs[i])
return (0);
return (1);
}
/*
* Put a string representation of an oid into a user buffer. This buffer
* is assumed to be at least ASN_OIDSTRLEN characters long.
*
* sprintf is assumed not to fail here.
*/
char *
asn_oid2str_r(const struct asn_oid *oid, char *buf)
{
u_int len, i;
char *ptr;
if ((len = oid->len) > ASN_MAXOIDLEN)
len = ASN_MAXOIDLEN;
buf[0] = '\0';
for (i = 0, ptr = buf; i < len; i++) {
if (i > 0)
*ptr++ = '.';
ptr += sprintf(ptr, "%u", oid->subs[i]);
}
return (buf);
}
/*
* Make a string from an OID in a private buffer.
*/
char *
asn_oid2str(const struct asn_oid *oid)
{
static char str[ASN_OIDSTRLEN];
return (asn_oid2str_r(oid, str));
}
static void
asn_error_func(const struct asn_buf *b, const char *err, ...)
{
va_list ap;
u_long i;
fprintf(stderr, "ASN.1: ");
va_start(ap, err);
vfprintf(stderr, err, ap);
va_end(ap);
if (b != NULL) {
fprintf(stderr, " at");
for (i = 0; b->asn_len > i; i++)
fprintf(stderr, " %02x", b->asn_cptr[i]);
}
fprintf(stderr, "\n");
}

186
contrib/bsnmp/lib/asn1.h Normal file
View File

@ -0,0 +1,186 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/lib/asn1.h,v 1.16 2002/02/11 10:19:57 hbb Exp $
*
* ASN.1 for SNMP
*/
#ifndef asn1_h_
#define asn1_h_
#include <sys/types.h>
struct asn_buf {
union {
u_char *ptr;
const u_char *cptr;
} asn_u;
size_t asn_len;
};
#define asn_cptr asn_u.cptr
#define asn_ptr asn_u.ptr
/* these restrictions are in the SMI */
#define ASN_MAXID 0xffffffff
#define ASN_MAXOIDLEN 128
/* the string needed for this (with trailing zero) */
#define ASN_OIDSTRLEN (ASN_MAXOIDLEN * (10 + 1) - 1 + 1)
/* type of subidentifiers */
typedef u_int32_t asn_subid_t;
struct asn_oid {
u_int len;
asn_subid_t subs[ASN_MAXOIDLEN];
};
enum asn_err {
/* conversion was ok */
ASN_ERR_OK = 0,
/* conversion failed and stopped */
ASN_ERR_FAILED = 1 | 0x1000,
/* length field bad, value skipped */
ASN_ERR_BADLEN = 2,
/* out of buffer, stopped */
ASN_ERR_EOBUF = 3 | 0x1000,
/* length ok, but value is out of range */
ASN_ERR_RANGE = 4,
/* not the expected tag, stopped */
ASN_ERR_TAG = 5 | 0x1000,
};
#define ASN_ERR_STOPPED(E) (((E) & 0x1000) != 0)
/* type for the length field of encoded values. The length is restricted
* to 65535, but using u_int16_t would give conversion warnings on gcc */
typedef u_int32_t asn_len_t; /* could be also u_int16_t */
/* maximal length of a long length field without the length of the length */
#define ASN_MAXLEN 65535
#define ASN_MAXLENLEN 2 /* number of bytes in a length */
/* maximum size of an octet string as per SMIv2 */
#define ASN_MAXOCTETSTRING 65535
extern void (*asn_error)(const struct asn_buf *, const char *, ...);
enum asn_err asn_get_header(struct asn_buf *, u_char *, asn_len_t *);
enum asn_err asn_put_header(struct asn_buf *, u_char, asn_len_t);
enum asn_err asn_put_temp_header(struct asn_buf *, u_char, u_char **);
enum asn_err asn_commit_header(struct asn_buf *, u_char *);
enum asn_err asn_get_integer_raw(struct asn_buf *, asn_len_t, int32_t *);
enum asn_err asn_get_integer(struct asn_buf *, int32_t *);
enum asn_err asn_put_integer(struct asn_buf *, int32_t);
enum asn_err asn_get_octetstring_raw(struct asn_buf *, asn_len_t, u_char *, u_int *);
enum asn_err asn_get_octetstring(struct asn_buf *, u_char *, u_int *);
enum asn_err asn_put_octetstring(struct asn_buf *, const u_char *, u_int);
enum asn_err asn_get_null_raw(struct asn_buf *b, asn_len_t);
enum asn_err asn_get_null(struct asn_buf *);
enum asn_err asn_put_null(struct asn_buf *);
enum asn_err asn_put_exception(struct asn_buf *, u_int);
enum asn_err asn_get_objid_raw(struct asn_buf *, asn_len_t, struct asn_oid *);
enum asn_err asn_get_objid(struct asn_buf *, struct asn_oid *);
enum asn_err asn_put_objid(struct asn_buf *, const struct asn_oid *);
enum asn_err asn_get_sequence(struct asn_buf *, asn_len_t *);
enum asn_err asn_get_ipaddress_raw(struct asn_buf *, asn_len_t, u_char *);
enum asn_err asn_get_ipaddress(struct asn_buf *, u_char *);
enum asn_err asn_put_ipaddress(struct asn_buf *, const u_char *);
enum asn_err asn_get_uint32_raw(struct asn_buf *, asn_len_t, u_int32_t *);
enum asn_err asn_put_uint32(struct asn_buf *, u_char, u_int32_t);
enum asn_err asn_get_counter64_raw(struct asn_buf *, asn_len_t, u_int64_t *);
enum asn_err asn_put_counter64(struct asn_buf *, u_int64_t);
enum asn_err asn_get_timeticks(struct asn_buf *, u_int32_t *);
enum asn_err asn_put_timeticks(struct asn_buf *, u_int32_t);
enum asn_err asn_skip(struct asn_buf *, asn_len_t);
/*
* Utility functions for OIDs
*/
/* get a sub-OID from the middle of another OID */
void asn_slice_oid(struct asn_oid *, const struct asn_oid *, u_int, u_int);
/* append an OID to another one */
void asn_append_oid(struct asn_oid *, const struct asn_oid *);
/* compare two OIDs */
int asn_compare_oid(const struct asn_oid *, const struct asn_oid *);
/* check whether the first is a suboid of the second one */
int asn_is_suboid(const struct asn_oid *, const struct asn_oid *);
/* format an OID into a user buffer of size ASN_OIDSTRLEN */
char *asn_oid2str_r(const struct asn_oid *, char *);
/* format an OID into a private static buffer */
char *asn_oid2str(const struct asn_oid *);
enum {
ASN_TYPE_BOOLEAN = 0x01,
ASN_TYPE_INTEGER = 0x02,
ASN_TYPE_BITSTRING = 0x03,
ASN_TYPE_OCTETSTRING = 0x04,
ASN_TYPE_NULL = 0x05,
ASN_TYPE_OBJID = 0x06,
ASN_TYPE_SEQUENCE = 0x10,
ASN_TYPE_CONSTRUCTED = 0x20,
ASN_CLASS_UNIVERSAL = 0x00,
ASN_CLASS_APPLICATION = 0x40,
ASN_CLASS_CONTEXT = 0x80,
ASN_CLASS_PRIVATE = 0xc0,
ASN_TYPE_MASK = 0x1f,
ASN_APP_IPADDRESS = 0x00,
ASN_APP_COUNTER = 0x01,
ASN_APP_GAUGE = 0x02,
ASN_APP_TIMETICKS = 0x03,
ASN_APP_OPAQUE = 0x04, /* not implemented */
ASN_APP_COUNTER64 = 0x06,
ASN_EXCEPT_NOSUCHOBJECT = 0x00,
ASN_EXCEPT_NOSUCHINSTANCE = 0x01,
ASN_EXCEPT_ENDOFMIBVIEW = 0x02,
};
#endif

View File

@ -0,0 +1,417 @@
.\"
.\" Copyright (c) 2001-2003
.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
.\" All rights reserved.
.\"
.\" Author: Harti Brandt <harti@freebsd.org>
.\"
.\" Redistribution of this software and documentation 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 or documentation 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.
.\" 3. Neither the name of the Institute nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
.\" AND ITS 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
.\" FRAUNHOFER FOKUS OR ITS 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/lib/bsnmpagent.3,v 1.1 2002/08/16 12:22:58 hbb Exp $
.\"
.Dd August 16, 2002
.Dt bsnmpagent 3
.Os
.Sh NAME
.Nm snmp_depop_t ,
.Nm snmp_set_finish_t ,
.Nm snmp_op_t ,
.Nm tree ,
.Nm tree_size ,
.Nm snmp_trace ,
.Nm snmp_debug ,
.Nm snmp_get ,
.Nm snmp_getnext ,
.Nm snmp_getbulk ,
.Nm snmp_set ,
.Nm snmp_make_errresp ,
.Nm snmp_dep_lookup ,
.Nm snmp_set_atfinish ,
.Nm snmp_init_context ,
.Nm snmp_dep_commit ,
.Nm snmp_dep_rollback
.Nd "SNMP agent library"
.Sh LIBRARY
Begemot SNMP library
.Pq libbsnmp, -lbsnmp
.Sh SYNOPSIS
.In asn1.h
.In snmp.h
.In snmpagent.h
.Ft typedef int
.Fn (*snmp_depop_t) "struct snmp_context *ctx" "struct snmp_dependency *dep" "enum snmp_depop op"
.Ft typedef void
.Fn (*snmp_set_finish_t) "struct snmp_context *ctx" "int fail" "void *uarg"
.Ft typedef int
.Fn (*snmp_op_t) "struct snmp_context *ctx" "struct snmp_value *val" "u_int len" "u_int idx" "enum snmp_op op"
.Vt extern struct snmp_node *tree ;
.Vt extern u_int tree_size ;
.Vt extern u_int snmp_trace ;
.Vt extern void (*snmp_debug)(const char *fmt, ...) ;
.Ft enum snmp_ret
.Fn snmp_get "struct snmp_pdu *pdu" "struct asn_buf *resp_b" "struct snmp_pdu *resp" "void *data"
.Ft enum snmp_ret
.Fn snmp_getnext "struct snmp_pdu *pdu" "struct asn_buf *resp_b" "struct snmp_pdu *resp" "void *data"
.Ft enum snmp_ret
.Fn snmp_getbulk "struct snmp_pdu *pdu" "struct asn_buf *resp_b" "struct snmp_pdu *resp" "void *data"
.Ft enum snmp_ret
.Fn snmp_set "struct snmp_pdu *pdu" "struct asn_buf *resp_b" "struct snmp_pdu *resp" "void *data"
.Ft enum snmp_ret
.Fn snmp_make_errresp "const struct snmp_pdu *pdu" "struct asn_buf *req_b" "struct asn_buf *resp_b"
.Ft struct snmp_dependency *
.Fn snmp_dep_lookup "struct snmp_context *ctx" "const struct asn_oid *base" "const struct asn_oid *idx" "size_t alloc" "snmp_depop_t func"
.Ft int
.Fn snmp_set_atfinish "struct snmp_context *ctx" "snmp_set_finish_t func" "void *uarg"
.Ft struct snmp_context *
.Fn snmp_init_context "void"
.Ft int
.Fn snmp_dep_commit "struct snmp_context *ctx"
.Ft int
.Fn snmp_dep_rollback "struct snmp_context *ctx"
.Sh DESCRIPTION
The SNMP library contains routines to easily build SNMP agent applications
that use SNMP versions 1 or 2. Note, however, that it may be even easier to
build an
.Xr snmpd 1
loadable module, that handles the new MIB (see
.Xr snmpmod 3 ).
.Pp
Most of the agent routines operate on a global array that the describes the
complete MIB served by the agent. This array is held in the two variables:
.Bd -literal -offset indent
extern struct snmp_node *tree;
extern u_int tree_size;
.Ed
.Pp
The elements of the array are of type
.Vt struct snmp_node :
.Bd -literal -offset indent
typedef int (*snmp_op_t)(struct snmp_context *, struct snmp_value *,
u_int, u_int, enum snmp_op);
struct snmp_node {
struct asn_oid oid;
const char *name; /* name of the leaf */
enum snmp_node_type type; /* type of this node */
enum snmp_syntax syntax;
snmp_op_t op;
u_int flags;
u_int32_t index; /* index data */
void *data; /* application data */
};
.Ed
.Pp
The fields of this structure are described below.
.Bl -tag -width "syntax"
.It Va oid
Base OID of the scalar or table column.
.It Va name
Name of this variable.
.It Va type
Type of this variable. One of:
.Bd -literal -offset indent
enum snmp_node_type {
SNMP_NODE_LEAF = 1,
SNMP_NODE_COLUMN
};
.Ed
.It Va syntax
The SNMP syntax of this variable.
.It Va op
The user supplied handler for this variable. The handler is called with
the following arguments:
.Bl -tag -width "ctx"
.It Fa ctx
A pointer to the context (see below).
.Li NULL .
.It Fa val
The value to be set or retrieved. For GETNEXT and GETBULK operations the oid in
this value is the current OID. The function (called in this case only for
table rows) must find the lexically next existing OID within the same column and
set the oid and value subfields accordingly. If the table column is exhausted the
function must return
.Li SNMP_ERR_NOSUCHNAME .
For all other operations the oid in
.Fa val
is the oid to fetch or set.
.It Fa len
The length of the base oid without index.
.It Fa idx
For table columns this is the index expression from the node (see below).
.It Fa op
This is the operation to execute, one of:
.Bd -literal -offset indent
enum snmp_op {
SNMP_OP_GET = 1,
SNMP_OP_GETNEXT,
SNMP_OP_SET,
SNMP_OP_COMMIT,
SNMP_OP_ROLLBACK,
};
.Ed
.El
.Pp
The user handler must return an appropiate SNMP v2 error code. If the original
PDU was a version 1 PDU, the error code is mapped automatically.
.It Va flags
Currently only the flag
.Li SNMP_NODE_CANSET is defined and set for nodes, that can be written or
created.
.It Va index
This word describes the index for table columns. Each part of the index
takes 4 bits starting at bit 4. Bits 0 to 3 hold the number of index parts.
This arrangment allows for tables with up to seven indexes. Each bit group
contains the syntax for the index part. There are a number of macros to
help in parsing this field:
.Bd -literal -offset indent
#define SNMP_INDEXES_MAX 7
#define SNMP_INDEX_SHIFT 4
#define SNMP_INDEX_MASK 0xf
#define SNMP_INDEX_COUNT(V) ((V) & SNMP_INDEX_MASK)
#define SNMP_INDEX(V,I) \e
(((V) >> (((I) + 1) * SNMP_INDEX_SHIFT)) & \e
SNMP_INDEX_MASK)
.Ed
.It Va data
This field may contain arbitrary data and is not used by the library.
.El
.Pp
The easiest way to construct the node table is
.Xr gensnmptree 1 .
Note, that one must be careful when changing the tree while executing a SET
operation. Consult the sources for
.Xr snmpd 1 .
.Pp
The global variable
.Va snmp_trace
together with the function pointed to by
.Va snmp_debug
help in debugging the library and the agent.
.Va snmp_trace is a bit mask with the following bits:
.Bd -literal -offset indent
enum {
SNMP_TRACE_GET,
SNMP_TRACE_GETNEXT,
SNMP_TRACE_SET,
SNMP_TRACE_DEPEND,
SNMP_TRACE_FIND,
};
.Ed
.Pp
Setting a bit to true causes the library to call
.Fn snmp_debug
in strategic places with a debug string. The library contains a default
implementation for the debug function that prints a message to standard error.
.Pp
Many of the functions use a so called context:
.Bd -literal -offset indent
struct snmp_context {
u_int var_index;
struct snmp_scratch *scratch;
struct snmp_dependency *dep;
void *data; /* user data */
};
struct snmp_scratch {
void *ptr1;
void *ptr2;
u_int32_t int1;
u_int32_t int2;
};
.Ed
.Pp
The fields are used as follows:
.Bl -tag -width ".It Va var_index"
.It Va va_index
For the node operation callback this is the
index of the variable binding that should be returned if an error occures.
Set by the library. In all other functions this is undefined.
.It Va scratch
For the node operation callback this is a pointer to a per variable binding
scratch area that can be used to implement the commit and rollback. Set
by the library.
.It Va dep
In the dependency callback function (see below) this is a pointer to the
current dependency. Set by the library.
.It Va data
This is the
.Fa data
argument from the call to the library and is not used by the library.
.El
.Pp
The next three functions execute different kinds of GET requests.
The function
.Fn snmp_get
executes an SNMP GET operation, the function
.Fn snmp_getnext
executes an SNMP GETNEXT operation and the function
.Fn snmp_getbulk
executes an SNMP GETBULK operation.
For all three functions the response PDU is constructed and encoded
on the fly. If everything is ok, the response PDU is returned in
.Fa resp
and
.Fa resp_b .
The caller must call
.Fn snmp_pdu_free
to free the response PDU in this case. One of the following values may be
returned:
.Bl -tag -width ".It Li SNMP_RET_ERR"
.It Li SNMP_RET_OK
Operation successful, response PDU may be sent.
.It Li SNMP_RET_IGN
Operation failed, no response PDU constructed. Request is ignored.
.It Li SNMP_RET_ERR
Error in operation. The error code and index have been set in
.Fa pdu .
No response PDU has been constructed.
The caller may construct an error response PDU via
.Fn snmp_make_errresp .
.El
.Pp
The function
.Fn snmp_set
executes an SNMP SET operation. The arguments are the same as for the previous
three functions. The operation of this functions is, however, much more complex.
.Pp
The SET operation occures in several stages:
.Bl -enum -offset indent
.It
For each binding search the corresponding nodes, check that the
variable is writeable and the syntax is ok. The writeable check can be done
only for scalars. For columns it must be done in the node's operation callback
function.
.It
For each binding call the node's operation callback with function SNMP_OP_SET.
The callback may create dependencies or finalizers (see below). For simple
scalars the scratch area may be enough to handle commit and rollback, for
interdependend table columns dependencies may be necessary.
.It
If the previous step fails at any point, the node's operation callback
functions are called for all bindings for which SNMP_OP_SET was executed
with SNMP_OP_ROLLBACK, in the opposite order. This allows all variables to
undo the effect of the SET operation. After this all the dependencies
are freed
and the finalizers are executed with a fail flag of 1. Then the function
returns to the caller with an appropriate error indication.
.It
If the SET step was successful for all bindings, the dependency callbacks
are executed in the order in which the dependencies were created with an
operation of SNMP_DEPOP_COMMIT. If any of the dependencies fails, all the
committed dependencies are called again in the opposite order
with SNMP_DEPOP_ROLLBACK. Than for all bindings from the last to the first
the node's operation callback is called with SNMP_OP_ROLLBACK to undo
the effect of SNMP_OP_SET. At the end the dependencies are freed
and the finalizers are called with a fail flag
of 1 and the function returns to the caller with an appropriate error indication.
.It
If the dependency commits were successful, for each binding the node's
operation callback is called with SNMP_OP_COMMIT. Any error returned from
the callbacks is ignored (an error message is generated via
.Fn snmp_error ).
.It
Now the dependencies are freed and the finalizers are called
with a fail flag of 0. Then the function returns
.Li SNMP_ERR_OK .
.El
.Pp
There are to mechanisms to help in complex SET operations: dependencies and
finalizers. A dependency is used if several bindings depend on each other.
A typical example is the creation of a conceptual row, which requires
the setting of several columns to succeed. A dependency is identified by
two OIDs. In the table case, the first oid is typically the table's base OID
and the second one the index. Both of these can easily be generated from the
variables OID with
.Fn asn_slice_oid .
The function
.Fn snmp_dep_lookup
tries to find a dependency based on these two OIDs and, if it cannot find one
creates a new one. This means for the table example, that the function
returns the same dependency for each of the columns of the same table row.
This allows during the SNMP_OP_SET processing to collect all information
about the row into the dependency. The arguments to
.Fn snmp_dep_lookup
are: the two OIDs to identify the dependency (they are copied into newly
created dependencies), the size of the structure to allocate and
the dependency callback.
.Pp
When all SNMP_OP_SET operations have succeeded the dependencies are executed.
At this stage the dependency callback has all information about the given
table row that was available in this SET PDU and can operate accordingly.
.Pp
If a SNMP_OP_SET operation fails, the dependency callbacks are never
called. The nodes SNMP_OP_ROLLBACK operations have to ensure, that
any dynamically allocated data is freed.
.Pp
Finalizers are a
.Sq last change
to do processing.
They are called after everything has been done, just before returning to the
user. They get a flag, that tells them, whether the return to the user is a good
one or not. The typical use is to finally remove deleted table elements.
Finalizers are created with
.Fn snmp_set_atfinish
which takes the callback function and a user data pointer as argument.
.Pp
The function
.Fn snmp_make_errresp
makes an error response if an operation has failed. It takes the original
request PDU (it will look only on the error code and index fields), the
buffer containing the original PDU and a buffer for the error PDU. It copies
the bindings field from the original PDUs buffer directly to the response
PDU and thus does not depend on the decodability of this field. It may return
the same values as the operation functions.
.Pp
The next three functions allow some parts of the SET operation to be executed.
This is only used in
.Xr snmpd 1
to implement the configuration as a single transaction.
The function
.Fn snmp_init_context
creates and initializes a context.
The function
.Fn snmp_dep_commit
executes SNMP_DEPOP_COMMIT for all dependencies in the context stopping at
the first error.
The function
.Fn snmp_dep_rollback
executes SNMP_DEPOP_ROLLBACK starting at the previous of the current
dependency in the context.
.Sh DIAGNOSTICS
If an error occures in any of the function an error indication as described
above is returned. Additionally the functions may call snmp_error on unexected
errors.
.Sh SEE ALSO
.Xr snmpd 1 ,
.Xr gensnmptree 1 ,
.Xr bsnmplib 3
.Xr bsnmpclient 3 ,
.Xr snmpmod 3
.Sh STANDARDS
This implementation conforms to the applicable IETF RFCs and ITU-T
recommendations.
.Sh AUTHORS
.An Hartmut Brandt Aq brandt@fokus.gmd.de

View File

@ -0,0 +1,590 @@
.\"
.\" Copyright (c) 2001-2003
.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
.\" All rights reserved.
.\"
.\" Author: Harti Brandt <harti@freebsd.org>
.\"
.\" Redistribution of this software and documentation 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 or documentation 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.
.\" 3. Neither the name of the Institute nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
.\" AND ITS 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
.\" FRAUNHOFER FOKUS OR ITS 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/lib/bsnmpclient.3,v 1.3 2002/12/11 15:54:07 hbb Exp $
.\"
.Dd August 15, 2002
.Dt bsnmpclient 3
.Os
.Sh NAME
.Nm snmp_client ,
.Nm snmp_send_cb_f ,
.Nm snmp_timeout_cb_f ,
.Nm snmp_timeout_start_f ,
.Nm snmp_timeout_stop_f ,
.Nm snmp_open ,
.Nm snmp_close ,
.Nm snmp_pdu_create ,
.Nm snmp_add_binding ,
.Nm snmp_pdu_check ,
.Nm snmp_pdu_send ,
.Nm snmp_oid_append ,
.Nm snmp_receive ,
.Nm snmp_table_cb_f ,
.Nm snmp_table_fetch ,
.Nm snmp_table_fetch_async ,
.Nm snmp_dialog
.Nd "SNMP client library"
.Sh LIBRARY
Begemot SNMP library
.Pq libbsnmp, -lbsnmp
.Sh SYNOPSIS
.In asn1.h
.In snmp.h
.In snmpclient.h
.Ft typedef void
.Fn (*snmp_send_cb_f) "struct snmp_pdu *req" "struct snmp_pdu *resp" "void *uarg"
.Ft typedef void
.Fn (*snmp_timeout_cb_f) "void *uarg"
.Ft typedef void *
.Fn (*snmp_timeout_start_f) "struct timeval *timeout" "snmp_timeout_cb_f callback" "void *uarg"
.Ft typedef void
.Fn (*snmp_timeout_stop_f) "void *timeout_id"
.Vt extern struct snmp_client snmp_client ;
.Ft void
.Fn snmp_client_init "struct snmp_client *client"
.Ft int
.Fn snmp_client_set_host "struct snmp_client *client" "const char *host"
.Ft int
.Fn snmp_client_set_port "struct snmp_client *client" "const char *port"
.Ft int
.Fn snmp_open "const char *host" "const char *port" "const char *read_community" "const char *write_community"
.Ft void
.Fn snmp_close "void"
.Ft void
.Fn snmp_pdu_create "struct snmp_pdu *pdu" "u_int op"
.Ft int
.Fn snmp_add_binding "struct snmp_pdu *pdu" "..."
.Ft int
.Fn snmp_pdu_check "const struct snmp_pdu *req" "const struct snmp_pdu *resp"
.Ft int32_t
.Fn snmp_pdu_send "struct snmp_pdu *pdu" "snmp_send_cb_f func" "void *uarg"
.Ft int
.Fn snmp_oid_append "struct asn_oid *oid" "const char *fmt" "..."
.Ft int
.Fn snmp_receive "int blocking"
.Ft typedef void
.Fn (*snmp_table_cb_f) "void *list" "void *arg" "int res"
.Ft int
.Fn snmp_table_fetch "const struct snmp_table *descr" "void *list"
.Ft int
.Fn snmp_table_fetch_async "const struct snmp_table *descr" "void *list" "snmp_table_cb_f callback" "void *uarg"
.Ft int
.Fn snmp_dialog "struct snmp_pdu *req" "struct snmp_pdu *resp"
.Sh DESCRIPTION
The SNMP library contains routines to easily build SNMP client applications
that use SNMP versions 1 or 2. Most of the routines use a
.Vt struct snmp_client :
.Bd -literal -offset indent
struct snmp_client {
enum snmp_version version;
int local; /* use local socket */
/* these two are read-only for the application */
char *cport; /* port number as string */
char *chost; /* host name or IP address as string */
char read_community[SNMP_COMMUNITY_MAXLEN + 1];
char write_community[SNMP_COMMUNITY_MAXLEN + 1];
struct timeval timeout;
u_int retries;
int dump_pdus;
size_t txbuflen;
size_t rxbuflen;
int fd;
int32_t next_reqid;
int32_t max_reqid;
int32_t min_reqid;
char error[SNMP_STRERROR_LEN];
snmp_timeout_start_f timeout_start;
snmp_timeout_stop_f timeout_stop;
/* private */
char local_path[sizeof(SNMP_LOCAL_PATH)];
};
.Ed
.Pp
The fields of this structure are described below.
.Bl -tag -width "timeout_start"
.It Va version
This is the version of SNMP to use. See
.Xr bsnmplib 3
for applicable values. The default version is
.Li SNMP_V2c .
.It Va local
If this is set to true, the library opens a
.Ux
domain socket rather than
an UDP socket. It uses the
.Va chost
field as the path to the server's socket.
.It Va cport
The SNMP agent's UDP port number. This may be a symbolic port number (from
.Pa /etc/services
or a numeric port number. If this field is
.Li NULL
(the default) the standard SNMP port is used. This field should not be changed
directly but rather by calling
.Fn snmp_client_set_port .
.It Va chost
The SNMP agent's host name, IP address or
.Ux
domain socket path name.
If this is
.Li NULL
(the default)
.Li localhost
is assumed. This field should not be changed directly but rather through
calling
.Fn snmp_client_set_host .
.It Va read_community
This is the community name to be used for all requests except SET requests.
The default is
.Sq public .
.It Va write_community
The community name to be used for SET requests. The default is
.Sq private .
.It Va timeout
The maximum time to wait for responses to requests. If the time elapses, the
request is resent up to
.Va retries
times. The default is 3 seconds.
.It Va retries
Number of times a request PDU is to be resent. If set to 0, the request is
sent only once. The default is 3 retransmissions.
.It Va dump_pdus
If set to a non-zero value all received and sent PDUs are dumped via
.Xr snmp_pdu_dump 3 .
The default is not to dump PDUs.
.It Va txbuflen
The encoding buffer size to be allocated for transmitted PDUs. The default is
10000 octets.
.It Va rxbuflen
The decoding buffer size to be allocated for received PDUs. This is the size
of the maximum PDU that can be received. The default is 10000 octets.
.It Va fd
After calling
.Fn snmp_open
this is the file socket file descriptor used for sending and receiving PDUs.
.It Va next_reqid
The request id of the next PDU to send. Used internal by the library.
.It Va max_reqid
The maximum request id to use for outging PDUs. The default is
.Li INT32_MAX .
.It Va min_reqid
The minimum request id to use for outgoing PDUs. Request ids are allocated
linerily starting at
.Va min_reqid
up to
.Va max_reqid .
.It Va error
If an error happens, this field is set to a printable string describing the
error.
.It Va timeout_start
This field must point to a function setting up a one shot timeout. After the
timeout has elapsed, the given callback function must be called with the
user argument. The
.Fn timeout_start
function must return a
.Vt void *
identifying the timeout.
.It Va timeout_stop
This field must be set to a function that stops a running timeout. The function
will be called with the return value of the corresponding
.Fn timeout_start
function.
.It Va local_path
If in local socket mode, the name of the clients socket. Not needed by the
application.
.El
.Pp
In the current implementation there is a global variable
.Bd -unfilled -offset indent
.Vt extern struct snmp_client snmp_client ;
.Ed
.Pp
that is used by all the library functions. The first call into the library must
be a call to
.Fn snmp_client_init
to initialize this global variable to the default values.
After this call and before calling
.Fn snmp_open
the fields of the variable may be modified by the user.
The modification of the
.Va chost
and
.Va cport
fields should be done only via the functions
.Fn snmp_client_set_host
and
.Fn snmp_client_set_port .
.Pp
The function
.Fn snmp_open
creates a UDP or
.Ux
domain socket and connects it to the agent's IP address and port.
If any of the arguments of the call is not
.Li NULL
the corresponding field in the global
.Va snmp_client
is set from the argument. Otherwise the values that are already in that variable
are used.
The function
.Fn snmp_close
closes the socket, stops all timeouts and frees all dynamically allocated
resources.
.Pp
The next three functions are used to create request PDUs. The function
.Fn snmp_pdu_create
initializes a PDU of type
.Va op .
It does not allocate space for the PDU itself. This is the responsibility of
the caller.
.Fn snmp_add_binding
adds bindings to the PDU and returns the (zero based) index of the first new
binding. The arguments are pairs of pointer to the OIDs and syntax constants,
terminated by a NULL. The call
.Bd -literal -offset indent
snmp_add_binding(&pdu,
&oid1, SNMP_SYNTAX_INTEGER,
&oid2, SNMP_SYNTAX_OCTETSTRING,
NULL);
.Ed
.Pp
adds two new bindings to the PDU and returns the index of the first one.
It is the responsibility of the caller to set the value part of the binding
if neccesary. The functions returns -1 if the maximum number of bindings
is exhausted.
The function
.Fn snmp_oid_append
can be used to construct variable OIDs for requests. It takes a pointer
to an
.Vt struct asn_oid
that is to be constructed, a format string, and a number of arguments
the type of which depends on the format string. The format string is interpreted
character by character in the following way:
.Bl -tag -width ".It Li ( Va N Ns Li )"
.It Li i
This format expects an argument of type
.Vt asn_subid_t
and appends this as a single integer to the OID.
.It Li a
This format expects an argument of type
.Vt struct in_addr
and appends to four parts of the IP address to the OID.
.It Li s
This format expects an argument of type
.Vt const char *
and appends the length of the string (as computed by
.Xr strlen 3 )
and each of the characters in the string to the OID.
.It Li ( Va N Ns Li )
This format expects no argument.
.Va N
must be a decimal number and is stored into an internal variable
.Va size .
.It Li b
This format expects an argument of type
.Vt const char *
and appends
.Va size
characters from the string to the OID. The string may contain
.Li NUL
characters.
.It Li c
This format expects two arguments: one of type
.Vt size_t
and one of type
.Vt const u_char * .
The first argument gives the number of bytes to append to the OID from the string
pointed to by the second argument.
.El
.Pp
The function
.Fn snmp_pdu_check
may be used to check a response PDU. A number of checks are performed
(error code, equal number of bindings, syntaxes and values for SET PDUs).
The function returns +1 if everything is ok, 0 if a NOSUCHNAME or similar
error was detected, -1 if the response PDU had fatal errors
and -2 if
.Fa resp
is
.Li NULL
(a timeout occured).
.Pp
The function
.Fn snmp_pdu_send
encodes and sends the given PDU. It records the PDU together with the callback
and user pointers in an internal list and arranges for retransmission if no
response is received. When a response is received or the retransmission count
is exceeded the callback
.Fa func
is called with the orignal request PDU, the response PDU and the user argument
.Fa uarg .
If the retransmit count is exceeded,
.Fa func
is called with the original request PDU, the reponse pointer set to
.Li NULL
and the user argument
.Fa uarg .
The caller should not free the request PDU until the callback function is
called. The callback function must free the request PDU and the response
PDU (if not
.Li NULL ).
.Pp
The function
.Fn snmp_receive
tries to receive a PDU. If the argument is zero, the function polls to see
whether a packet is available, if the argument is non-zero, the function blocks
until the next packet is received. The packet is delivered via the usual callback
mechanism (non-response packets are silently dropped).
The function returns 0, if a packet was received and successfully dispatched,
-1 if an error occured or no packet was available (in polling mode).
.Pp
The next two functions are used to retrieve tables from SNMP agents. The use
the following input structure, that describes the table:
.Bd -literal -offset indent
struct snmp_table {
struct asn_oid table;
struct asn_oid last_change;
u_int max_iter;
size_t entry_size;
u_int index_size;
u_int64_t req_mask;
struct snmp_table_entry {
asn_subid_t subid;
enum snmp_syntax syntax;
off_t offset;
} entries[];
};
.Ed
.Pp
The fields of this structure have the following meaning:
.Bl -tag -width "last_change"
.It Va table
This is the base OID of the table.
.It Va last_change
Some tables have a scalar variable of type TIMETICKS attached to them,
that holds the time when the table was last changed. This OID should be
the OID of this variable (without the \&.0 index). When the table is retrieved
with multiple GET requests, and the variable changes between two request,
the table fetch is restarted.
.It Va max_iter
Maximum number of tries to fetch the table.
.It Va entry_size
The table fetching routines return a list of structure one for each table
row. This variable is the size of one structure and used to
.Xr malloc 3
the structure.
.It Va index_size
This is the number of index columns in the table.
.It Va req_mask
This is a bit mask with a 1 for each table column that is required.
Bit 0 corresponds to the first element (index 0) in the array
.Va entries ,
bit 1 to the second (index 1) and so on. SNMP tables may be sparse. For sparse
columns the bit should not be set. If the bit for a given column is set and
the column value cannot be retrieved for a given row, the table fetch is
restarted assuming that the table is currently beeing modified by the agent.
The bits for the index columns are ignored.
.It Va entries
This is a variable sized array of column descriptors. This array is terminated
by an element with syntax
.Li SNMP_SYNTAX_NULL .
The first
.Va index_size
elements describe all the index columns of the table, the rest are normal
columns. If for a the column at
.Ql entries[N]
the expression
.Ql req_mask & (1 << N)
yields true, the column is considered a required column.
The fields of this the array elements have the following meaning:
.Bl -tag -width "syntax"
.It Va subid
This is the OID subid of the column. This is ignored for index entries. Index
entries are decoded according to the
.Va syntax
field.
.It Va syntax
This is the syntax of the column or index. A syntax of
.Li SNMP_SYNTAX_NULL
terminates the array.
.It Va offset
This is the starting offset of the value of the column in the return structures.
This field can be set with the ISO-C
.Fn offsetof
macro.
.El
.El
.Pp
Both table fetching functions return TAILQ (see
.Xr queue 3 )
of structures--one for each table row. These structures must start with a
.Fn TAILQ_ENTRY
and a
.Vt u_int64_t
and are allocated via
.Xr malloc 3 .
The
.Fa list
argument of the table functions must point to a
.Fn TAILQ_HEAD .
The
.Vt u_int64_t
fields, usually called
.Va found
is used to indicate which of the columns have been found for the given
row. It is encoded like the
.Fa req_mask
field.
.Pp
The function
.Fn snmp_table_fetch
synchronuosly fetches the given table. If everything is ok 0 is returned.
Otherwise the function returns -1 and sets an appropriate error string.
The function
.Fn snmp_table_fetch_async
fetches the tables asynchronuosly. If either the entire table is fetch, or
an error occures the callback function
.Fa callback
is called with the callers arguments
.Fa list
and
.Fa uarg
and a parameter that is either 0 if the table was fetched, or
-1 if there was an error. The function itself returns -1 if it could not
initialize fetching of the table.
.Pp
The following table description is used to fetch the ATM interface table:
.Bd -literal -offset indent
/*
* ATM interface table
*/
struct atmif {
TAILQ_ENTRY(atmif) link;
u_int64_t found;
int32_t index;
u_char *ifname;
size_t ifnamelen;
u_int32_t node_id;
u_int32_t pcr;
int32_t media;
u_int32_t vpi_bits;
u_int32_t vci_bits;
u_int32_t max_vpcs;
u_int32_t max_vccs;
u_char *esi;
size_t esilen;
int32_t carrier;
};
TAILQ_HEAD(atmif_list, atmif);
/* list of all ATM interfaces */
struct atmif_list atmif_list;
static const struct snmp_table atmif_table = {
OIDX_begemotAtmIfTable,
OIDX_begemotAtmIfTableLastChange, 2,
sizeof(struct atmif),
1, 0x7ffULL,
{
{ 0, SNMP_SYNTAX_INTEGER,
offsetof(struct atmif, index) },
{ 1, SNMP_SYNTAX_OCTETSTRING,
offsetof(struct atmif, ifname) },
{ 2, SNMP_SYNTAX_GAUGE,
offsetof(struct atmif, node_id) },
{ 3, SNMP_SYNTAX_GAUGE,
offsetof(struct atmif, pcr) },
{ 4, SNMP_SYNTAX_INTEGER,
offsetof(struct atmif, media) },
{ 5, SNMP_SYNTAX_GAUGE,
offsetof(struct atmif, vpi_bits) },
{ 6, SNMP_SYNTAX_GAUGE,
offsetof(struct atmif, vci_bits) },
{ 7, SNMP_SYNTAX_GAUGE,
offsetof(struct atmif, max_vpcs) },
{ 8, SNMP_SYNTAX_GAUGE,
offsetof(struct atmif, max_vccs) },
{ 9, SNMP_SYNTAX_OCTETSTRING,
offsetof(struct atmif, esi) },
{ 10, SNMP_SYNTAX_INTEGER,
offsetof(struct atmif, carrier) },
{ 0, SNMP_SYNTAX_NULL, 0 }
}
};
\&...
if (snmp_table_fetch(&atmif_table, &atmif_list) != 0)
errx(1, "AtmIf table: %s", snmp_client.error);
\&...
.Ed
.Pp
The function
.Fn snmp_dialog
is used to execute a synchonuous dialog with the agent. The request PDU
.Fa req
is sent and the function blocks until the response PDU is received. Note,
that asynchonuous receives are handled (i.e. callback functions of other send
calls or table fetches may be called while in the function). The response
PDU is returned in
.Fa resp .
If no reponse could be received after all timeouts and retries, the function
returns -1. If a response was received 0 is returned.
.Sh DIAGNOSTICS
If an error occures in any of the function an error indication as described
above is returned. Additionally the function sets a printable error string
in the
.Va error
filed of
.Va snmp_client .
.Sh SEE ALSO
.Xr snmpd 1 ,
.Xr gensnmptree 1 ,
.Xr bsnmplib 3
.Xr bsnmpagent 3
.Sh STANDARDS
This implementation conforms to the applicable IETF RFCs and ITU-T
recommendations.
.Sh AUTHORS
.An Hartmut Brandt Aq brandt@fokus.gmd.de
.An Kendy Kutzner Aq kutzner@fokus.gmd.de

View File

@ -0,0 +1,306 @@
.\"
.\" Copyright (c) 2001-2003
.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
.\" All rights reserved.
.\"
.\" Author: Harti Brandt <harti@freebsd.org>
.\"
.\" Redistribution of this software and documentation 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 or documentation 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.
.\" 3. Neither the name of the Institute nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
.\" AND ITS 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
.\" FRAUNHOFER FOKUS OR ITS 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/lib/bsnmplib.3,v 1.2 2002/08/16 10:02:53 hbb Exp $
.\"
.Dd August 15, 2002
.Dt bsnmplib 3
.Os
.Sh NAME
.Nm snmp_value_free ,
.Nm snmp_value_parse ,
.Nm snmp_value_copy ,
.Nm snmp_pdu_free ,
.Nm snmp_code snmp_pdu_decode ,
.Nm snmp_code snmp_pdu_encode ,
.Nm snmp_pdu_dump ,
.Nm TRUTH_MK ,
.Nm TRUTH_GET ,
.Nm TRUTH_OK
.Nd "SNMP decoding and encoding library"
.Sh LIBRARY
Begemot SNMP library
.Pq libbsnmp, -lbsnmp
.Sh SYNOPSIS
.In bsnmp/asn1.h
.In bsnmp/snmp.h
.Ft void
.Fn snmp_value_free "struct snmp_value *value"
.Ft int
.Fn snmp_value_parse "const char *buf" "enum snmp_syntax" "union snmp_values *value"
.Ft int
.Fn snmp_value_copy "struct snmp_value *to" "const struct snmp_value *from"
.Ft void
.Fn snmp_pdu_free "struct snmp_pdu *value"
.Ft enum snmp_code
.Fn snmp_pdu_decode "struct asn_buf *buf" "struct snmp_pdu *pdu" "int32_t *ip"
.Ft enum snmp_code
.Fn snmp_pdu_encode "struct snmp_pdu *pdu" "struct asn_buf *buf"
.Ft void
.Fn snmp_pdu_dump "const struct snmp_pdu *pdu"
.Ft int
.Fn TRUTH_MK "F"
.Ft int
.Fn TRUTH_GET "T"
.Ft int
.Fn TRUTH_OK "T"
.Sh DESCRIPTION
The SNMP library contains routines to handle SNMP version 1 and 2 PDUs.
There are two basic structures used throughout the library:
.Bd -literal -offset indent
struct snmp_value {
struct asn_oid var;
enum snmp_syntax syntax;
union snmp_values {
int32_t integer;/* also integer32 */
struct {
u_int len;
u_char *octets;
} octetstring;
struct asn_oid oid;
u_char ipaddress[4];
u_int32_t uint32; /* also gauge32, counter32,
unsigned32, timeticks */
u_int64_t counter64;
} v;
};
.Ed
.Pp
This structure represents one variable binding from an SNMP PDU. The
field
.Fa var
is the ASN.1 of the variable that is bound.
.Fa syntax
contains either the syntax code of the value or an exception code for SNMPv2
and may be one of:
.Bd -literal -offset indent
enum snmp_syntax {
SNMP_SYNTAX_NULL = 0,
SNMP_SYNTAX_INTEGER, /* == INTEGER32 */
SNMP_SYNTAX_OCTETSTRING,
SNMP_SYNTAX_OID,
SNMP_SYNTAX_IPADDRESS,
SNMP_SYNTAX_COUNTER,
SNMP_SYNTAX_GAUGE, /* == UNSIGNED32 */
SNMP_SYNTAX_TIMETICKS,
/* v2 additions */
SNMP_SYNTAX_COUNTER64,
/* exceptions */
SNMP_SYNTAX_NOSUCHOBJECT,
SNMP_SYNTAX_NOSUCHINSTANCE,
SNMP_SYNTAX_ENDOFMIBVIEW,
};
.Ed
The field
.Fa v
holds the actual value depending on
.Fa syntax .
Note, that if
.Fa syntax
is
.Li SNMP_SYNTAX_OCTETSTRING
and
.Fa v.octetstring.len
is not zero,
.Fa v.octetstring.octets
points to a string allocated by
.Xr malloc 3 .
.Pp
.Bd -literal -offset indent
#define SNMP_COMMUNITY_MAXLEN 128
#define SNMP_MAX_BINDINGS 100
struct snmp_pdu {
char community[SNMP_COMMUNITY_MAXLEN + 1];
enum snmp_version version;
u_int type;
/* trap only */
struct asn_oid enterprise;
u_char agent_addr[4];
int32_t generic_trap;
int32_t specific_trap;
u_int32_t time_stamp;
/* others */
int32_t request_id;
int32_t error_status;
int32_t error_index;
/* fixes for encoding */
u_char *outer_ptr;
u_char *pdu_ptr;
u_char *vars_ptr;
struct snmp_value bindings[SNMP_MAX_BINDINGS];
u_int nbindings;
};
.Ed
This structure contains a decoded SNMP PDU.
.Fa version
is one of
.Bd -literal -offset indent
enum snmp_version {
SNMP_Verr = 0,
SNMP_V1 = 1,
SNMP_V2c,
};
.Ed
and
.Fa type
is the type of the PDU.
.Pp
The function
.Fn snmp_value_free
is used to free all the dynamic allocated contents of an SNMP value. It does
not free the structure pointed to by
.Fa value
itself.
.Pp
The function
.Fn snmp_value_parse
parses the ASCII representation of an SNMP value into its binary form.
This function is mainly used by the configuration file reader of
.Xr snmpd 1 .
.Pp
The function
.Fn snmp_value_copy
makes a deep copy of the value pointed to by
.Fa from
to the structure pointed to by
.Fa to .
It assumes that
.Fa to
is uninitialized and will overwrite its previous contents. It does not itself
allocate the structure pointed to by
.Fa to .
.Pp
The function
.Fn snmp_pdu_free
frees all the dynamically allocated components of the PDU. It does not itself
free the structure pointed to by
.Fa pdu .
.Pp
The function
.Fn snmp_pdu_decode
decodes the PDU pointed to by
.Fa buf
and stores the result into
.Fa pdu .
If an error occurs in a variable binding the (1 based) index of this binding
is stored in the variable pointed to by
.Fa ip .
.Pp
The function
.Fn snmp_pdu_encode
encodes the PDU
.Fa pdu
into the an octetstring in buffer
.Fa buf .
.Pp
The function
.Fn snmp_pdu_dump
dumps the PDU in a human readable form by calling
.Fn snmp_printf .
.Pp
The function
.Fn TRUTH_MK
takes a C truth value (zero or non-zero) and makes an SNMP truth value (2 or 1).
The function
.Fn TRUTH_GET
takes an SNMP truth value and makes a C truth value (0 or 1).
The function
.Fn TRUTH_OK
checks, whether its argument is a legal SNMP truth value.
.Sh DIAGNOSTICS
When an error occures in any of the function the function pointed to
by the global pointer
.Bd -literal -offset indent
extern void (*snmp_error)(const char *, ...);
.Ed
.Pp
with a
.Xr printf 3
style format string.
There is a default error handler in the library that prints a message
starting with
.Sq SNMP:
followed by the error message to standard error.
.Pp
The function pointed to by
.Bd -literal -offset indent
extern void (*snmp_printf)(const char *, ...);
.Ed
.Pp
is called by the
.Fn snmp_pdu_dump
function.
The default handler is
.Xr printf 3 .
.Sh ERRORS
.Fn snmp_pdu_decode
will return one of the following return codes:
.Bl -tag -width Er
.It Bq Er SNMP_CODE_OK
Success.
.It Bq Er SNMP_CODE_FAILED
The ASN.1 coding was wrong.
.It Bq Er SNMP_CODE_BADLEN
A variable binding value had a wrong length field.
.It Bq Er SNMP_CODE_OORANGE
A variable binding value was out of the allowed range.
.It Bq Er SNMP_CODE_BADVERS
The PDU is of an unsupported version.
.It Bq Er SNMP_CODE_BADENQ
There was an ASN.1 value with an unsupported tag.
.El
.Pp
.Fn snmp_pdu_encode
will return one of the following return codes:
.Bl -tag -width Er
.It Bq Er SNMP_CODE_OK
Success.
.It Bq Er SNMP_CODE_FAILED
Encoding failed.
.El
.Sh SEE ALSO
.Xr snmpd 1 ,
.Xr gensnmptree 1 ,
.Xr bsnmplib 3
.Xr bsnmpclient 3 ,
.Xr bsnmpagent 3
.Sh STANDARDS
This implementation conforms to the applicable IETF RFCs and ITU-T
recommendations.
.Sh AUTHORS
.An Hartmut Brandt Aq brandt@fokus.gmd.de

1027
contrib/bsnmp/lib/snmp.c Normal file

File diff suppressed because it is too large Load Diff

176
contrib/bsnmp/lib/snmp.h Normal file
View File

@ -0,0 +1,176 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/lib/snmp.h,v 1.27 2002/03/08 14:24:58 hbb Exp $
*
* Header file for SNMP functions.
*/
#ifndef snmp_h_
#define snmp_h_
#include <sys/types.h>
#define SNMP_COMMUNITY_MAXLEN 128
#define SNMP_MAX_BINDINGS 100
enum snmp_syntax {
SNMP_SYNTAX_NULL = 0,
SNMP_SYNTAX_INTEGER, /* == INTEGER32 */
SNMP_SYNTAX_OCTETSTRING,
SNMP_SYNTAX_OID,
SNMP_SYNTAX_IPADDRESS,
SNMP_SYNTAX_COUNTER,
SNMP_SYNTAX_GAUGE, /* == UNSIGNED32 */
SNMP_SYNTAX_TIMETICKS,
/* v2 additions */
SNMP_SYNTAX_COUNTER64,
SNMP_SYNTAX_NOSUCHOBJECT, /* exception */
SNMP_SYNTAX_NOSUCHINSTANCE, /* exception */
SNMP_SYNTAX_ENDOFMIBVIEW, /* exception */
};
struct snmp_value {
struct asn_oid var;
enum snmp_syntax syntax;
union snmp_values {
int32_t integer; /* also integer32 */
struct {
u_int len;
u_char *octets;
} octetstring;
struct asn_oid oid;
u_char ipaddress[4];
u_int32_t uint32; /* also gauge32, counter32,
unsigned32, timeticks */
u_int64_t counter64;
} v;
};
enum snmp_version {
SNMP_Verr = 0,
SNMP_V1 = 1,
SNMP_V2c,
};
struct snmp_pdu {
char community[SNMP_COMMUNITY_MAXLEN + 1];
enum snmp_version version;
u_int type;
/* trap only */
struct asn_oid enterprise;
u_char agent_addr[4];
int32_t generic_trap;
int32_t specific_trap;
u_int32_t time_stamp;
/* others */
int32_t request_id;
int32_t error_status;
int32_t error_index;
/* fixes for encoding */
u_char *outer_ptr;
u_char *pdu_ptr;
u_char *vars_ptr;
struct snmp_value bindings[SNMP_MAX_BINDINGS];
u_int nbindings;
};
#define snmp_v1_pdu snmp_pdu
#define SNMP_PDU_GET 0
#define SNMP_PDU_GETNEXT 1
#define SNMP_PDU_RESPONSE 2
#define SNMP_PDU_SET 3
#define SNMP_PDU_TRAP 4 /* v1 */
#define SNMP_PDU_GETBULK 5 /* v2 */
#define SNMP_PDU_INFORM 6 /* v2 */
#define SNMP_PDU_TRAP2 7 /* v2 */
#define SNMP_PDU_REPORT 8 /* v2 */
#define SNMP_ERR_NOERROR 0
#define SNMP_ERR_TOOBIG 1
#define SNMP_ERR_NOSUCHNAME 2 /* v1 */
#define SNMP_ERR_BADVALUE 3 /* v1 */
#define SNMP_ERR_READONLY 4 /* v1 */
#define SNMP_ERR_GENERR 5
#define SNMP_ERR_NO_ACCESS 6 /* v2 */
#define SNMP_ERR_WRONG_TYPE 7 /* v2 */
#define SNMP_ERR_WRONG_LENGTH 8 /* v2 */
#define SNMP_ERR_WRONG_ENCODING 9 /* v2 */
#define SNMP_ERR_WRONG_VALUE 10 /* v2 */
#define SNMP_ERR_NO_CREATION 11 /* v2 */
#define SNMP_ERR_INCONS_VALUE 12 /* v2 */
#define SNMP_ERR_RES_UNAVAIL 13 /* v2 */
#define SNMP_ERR_COMMIT_FAILED 14 /* v2 */
#define SNMP_ERR_UNDO_FAILED 15 /* v2 */
#define SNMP_ERR_AUTH_ERR 16 /* v2 */
#define SNMP_ERR_NOT_WRITEABLE 17 /* v2 */
#define SNMP_ERR_INCONS_NAME 18 /* v2 */
#define SNMP_TRAP_COLDSTART 0
#define SNMP_TRAP_WARMSTART 1
#define SNMP_TRAP_LINKDOWN 2
#define SNMP_TRAP_LINKUP 3
#define SNMP_TRAP_AUTHENTICATION_FAILURE 4
#define SNMP_TRAP_EGP_NEIGHBOR_LOSS 5
#define SNMP_TRAP_ENTERPRISE 6
enum snmp_code {
SNMP_CODE_OK = 0,
SNMP_CODE_FAILED,
SNMP_CODE_BADVERS,
SNMP_CODE_BADLEN,
SNMP_CODE_BADENC,
SNMP_CODE_OORANGE,
};
void snmp_value_free(struct snmp_value *);
int snmp_value_parse(const char *, enum snmp_syntax, union snmp_values *);
int snmp_value_copy(struct snmp_value *, const struct snmp_value *);
void snmp_pdu_free(struct snmp_pdu *);
enum snmp_code snmp_pdu_decode(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *);
enum snmp_code snmp_pdu_encode(struct snmp_pdu *pdu, struct asn_buf *resp_b);
void snmp_pdu_dump(const struct snmp_pdu *pdu);
extern void (*snmp_error)(const char *, ...);
extern void (*snmp_printf)(const char *, ...);
#define TRUTH_MK(F) ((F) ? 1 : 2)
#define TRUTH_GET(T) (((T) == 1) ? 1 : 0)
#define TRUTH_OK(T) ((T) == 1 || (T) == 2)
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,159 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/lib/snmpagent.h,v 1.9 2002/03/08 14:24:58 hbb Exp $
*
* Header file for SNMP functions. This requires snmp.h to be included.
*/
#ifndef snmp_agent_h_
#define snmp_agent_h_
struct snmp_dependency;
/* Semi-Opaque object for SET operations */
struct snmp_context {
u_int var_index;
struct snmp_scratch *scratch;
struct snmp_dependency *dep;
void *data; /* user data */
};
struct snmp_scratch {
void *ptr1;
void *ptr2;
u_int32_t int1;
u_int32_t int2;
};
enum snmp_depop {
SNMP_DEPOP_COMMIT,
SNMP_DEPOP_ROLLBACK
};
typedef int (*snmp_depop_t)(struct snmp_context *, struct snmp_dependency *,
enum snmp_depop);
struct snmp_dependency {
struct asn_oid obj;
struct asn_oid idx;
};
/*
* Functions to be called at the end of a SET operation.
*/
typedef void (*snmp_set_finish_t)(struct snmp_context *, int fail, void *);
/*
* The TREE
*/
enum snmp_node_type {
SNMP_NODE_LEAF = 1,
SNMP_NODE_COLUMN
};
enum snmp_op {
SNMP_OP_GET = 1,
SNMP_OP_GETNEXT,
SNMP_OP_SET,
SNMP_OP_COMMIT,
SNMP_OP_ROLLBACK,
};
enum snmp_ret {
/* OK, generate a response */
SNMP_RET_OK = 0,
/* Error, ignore packet (no response) */
SNMP_RET_IGN = 1,
/* Error, generate response from original packet */
SNMP_RET_ERR = 2
};
typedef int (*snmp_op_t)(struct snmp_context *, struct snmp_value *,
u_int, u_int, enum snmp_op);
struct snmp_node {
struct asn_oid oid;
const char *name; /* name of the leaf */
enum snmp_node_type type; /* type of this node */
enum snmp_syntax syntax;
snmp_op_t op;
u_int flags;
u_int32_t index; /* index data */
void *data; /* application data */
};
extern struct snmp_node *tree;
extern u_int tree_size;
#define SNMP_NODE_CANSET 0x0001 /* SET allowed */
#define SNMP_INDEXES_MAX 7
#define SNMP_INDEX_SHIFT 4
#define SNMP_INDEX_MASK 0xf
#define SNMP_INDEX_COUNT(V) ((V) & SNMP_INDEX_MASK)
#define SNMP_INDEX(V,I) \
(((V) >> (((I) + 1) * SNMP_INDEX_SHIFT)) & SNMP_INDEX_MASK)
enum {
SNMP_TRACE_GET = 0x00000001,
SNMP_TRACE_GETNEXT = 0x00000002,
SNMP_TRACE_SET = 0x00000004,
SNMP_TRACE_DEPEND = 0x00000008,
SNMP_TRACE_FIND = 0x00000010,
};
/* trace flag for the following functions */
extern u_int snmp_trace;
/* called to write the trace */
extern void (*snmp_debug)(const char *fmt, ...);
enum snmp_ret snmp_get(struct snmp_pdu *pdu, struct asn_buf *resp_b,
struct snmp_pdu *resp, void *);
enum snmp_ret snmp_getnext(struct snmp_pdu *pdu, struct asn_buf *resp_b,
struct snmp_pdu *resp, void *);
enum snmp_ret snmp_getbulk(struct snmp_pdu *pdu, struct asn_buf *resp_b,
struct snmp_pdu *resp, void *);
enum snmp_ret snmp_set(struct snmp_pdu *pdu, struct asn_buf *resp_b,
struct snmp_pdu *resp, void *);
enum snmp_ret snmp_make_errresp(const struct snmp_pdu *, struct asn_buf *,
struct asn_buf *);
struct snmp_dependency *snmp_dep_lookup(struct snmp_context *,
const struct asn_oid *, const struct asn_oid *, size_t, snmp_depop_t);
int snmp_set_atfinish(struct snmp_context *, snmp_set_finish_t func, void *arg);
struct snmp_context *snmp_init_context(void);
int snmp_dep_commit(struct snmp_context *);
int snmp_dep_rollback(struct snmp_context *);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,182 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
* Kendy Kutzner
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/lib/snmpclient.h,v 1.15 2002/12/11 15:54:07 hbb Exp $
*/
#ifndef _BSNMP_SNMPCLIENT_H
#define _BSNMP_SNMPCLIENT_H
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <stddef.h>
#define SNMP_STRERROR_LEN 200
#define SNMP_LOCAL_PATH "/tmp/snmpXXXXXXXXXXXXXX"
/* type of callback function for responses
* this callback function is responsible for free() any memory associated with
* any of the PDUs. Therefor it may call snmp_pdu_free() */
typedef void (*snmp_send_cb_f)(struct snmp_pdu *, struct snmp_pdu *, void *);
/* type of callback function for timeouts */
typedef void (*snmp_timeout_cb_f)(void * );
/* timeout start function */
typedef void *(*snmp_timeout_start_f)(struct timeval *timeout,
snmp_timeout_cb_f callback, void *);
/* timeout stop function */
typedef void (*snmp_timeout_stop_f)(void *timeout_id);
/*
* Client context.
*/
struct snmp_client {
enum snmp_version version;
int local; /* use local socket */
/* these two are read-only for the application */
char *cport; /* port number as string */
char *chost; /* host name or IP address as string */
char read_community[SNMP_COMMUNITY_MAXLEN + 1];
char write_community[SNMP_COMMUNITY_MAXLEN + 1];
struct timeval timeout;
u_int retries;
int dump_pdus;
size_t txbuflen;
size_t rxbuflen;
int fd;
int32_t next_reqid;
int32_t max_reqid;
int32_t min_reqid;
char error[SNMP_STRERROR_LEN];
snmp_timeout_start_f timeout_start;
snmp_timeout_stop_f timeout_stop;
char local_path[sizeof(SNMP_LOCAL_PATH)];
};
/* the global context */
extern struct snmp_client snmp_client;
/* initizialies a snmp_client structure */
void snmp_client_init(struct snmp_client *);
/* initialize fields */
int snmp_client_set_host(struct snmp_client *, const char *);
int snmp_client_set_port(struct snmp_client *, const char *);
/* open connection to snmp server (hostname or portname can be NULL) */
int snmp_open(const char *_hostname, const char *_portname,
const char *_read_community, const char *_write_community);
/* close connection */
void snmp_close(void);
/* initialize a snmp_pdu structure */
void snmp_pdu_create(struct snmp_pdu *, u_int _op);
/* add pairs of (struct asn_oid *, enum snmp_syntax) to an existing pdu */
int snmp_add_binding(struct snmp_pdu *, ...);
/* check wheater the answer is valid or not */
int snmp_pdu_check(const struct snmp_pdu *_req, const struct snmp_pdu *_resp);
int32_t snmp_pdu_send(struct snmp_pdu *_pdu, snmp_send_cb_f _func, void *_arg);
/* append an index to an oid */
int snmp_oid_append(struct asn_oid *_oid, const char *_fmt, ...);
/* receive a packet */
int snmp_receive(int _blocking);
/*
* This structure is used to describe an SNMP table that is to be fetched.
* The C-structure that is produced by the fetch function must start with
* a TAILQ_ENTRY and an u_int64_t.
*/
struct snmp_table {
/* base OID of the table */
struct asn_oid table;
/* type OID of the LastChange variable for the table if any */
struct asn_oid last_change;
/* maximum number of iterations if table has changed */
u_int max_iter;
/* size of the C-structure */
size_t entry_size;
/* number of index fields */
u_int index_size;
/* bit mask of required fields */
u_int64_t req_mask;
/* indexes and columns to fetch. Ended by a NULL syntax entry */
struct snmp_table_entry {
/* the column sub-oid, ignored for index fields */
asn_subid_t subid;
/* the syntax of the column or index */
enum snmp_syntax syntax;
/* offset of the field into the C-structure. For octet strings
* this points to an u_char * followed by a size_t */
off_t offset;
#if defined(__GNUC__) && __GNUC__ < 3
} entries[0];
#else
} entries[];
#endif
};
/* callback type for table fetch */
typedef void (*snmp_table_cb_f)(void *_list, void *_arg, int _res);
/* fetch a table. The argument points to a TAILQ_HEAD */
int snmp_table_fetch(const struct snmp_table *descr, void *);
int snmp_table_fetch_async(const struct snmp_table *, void *,
snmp_table_cb_f, void *);
/* send a request and wait for the response */
int snmp_dialog(struct snmp_pdu *_req, struct snmp_pdu *_resp);
#endif /* _BSNMP_SNMPCLIENT_H */

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/lib/snmppriv.h,v 1.7 2002/12/11 15:54:07 hbb Exp $
*
* Private functions.
*/
enum asn_err snmp_binding_encode(struct asn_buf *, const struct snmp_value *);
enum snmp_code snmp_pdu_encode_header(struct asn_buf *, struct snmp_pdu *);
enum snmp_code snmp_fix_encoding(struct asn_buf *, const struct snmp_pdu *);
enum asn_err snmp_parse_message_hdr(struct asn_buf *b, struct snmp_pdu *pdu,
asn_len_t *lenp);
enum asn_err snmp_parse_pdus_hdr(struct asn_buf *b, struct snmp_pdu *pdu,
asn_len_t *lenp);
#define DEFAULT_HOST "localhost"
#define DEFAULT_PORT "snmp"
#define DEFAULT_LOCAL "/var/run/snmp.sock"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,238 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/snmp_mibII/mibII.h,v 1.11 2002/03/21 10:43:06 hbb Exp $
*
* Implementation of the interfaces and IP groups of MIB-II.
*/
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/syslog.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <err.h>
#include <ctype.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_mib.h>
#include <net/route.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "asn1.h"
#include "snmp.h"
#include "snmpmod.h"
#include "snmp_mibII.h"
#include "mibII_tree.h"
/*
* Interface list and flags.
*/
TAILQ_HEAD(mibif_list, mibif);
enum {
MIBIF_FOUND = 0x0001,
MIBIF_HIGHSPEED = 0x0002,
MIBIF_VERYHIGHSPEED = 0x0004,
};
#define hc_inoctets mib.ifmd_data.ifi_ibytes
#define hc_outoctets mib.ifmd_data.ifi_obytes
#define hc_omcasts mib.ifmd_data.ifi_omcasts
#define hc_opackets mib.ifmd_data.ifi_opackets
#define hc_imcasts mib.ifmd_data.ifi_imcasts
#define hc_ipackets mib.ifmd_data.ifi_ipackets
/*
* Interface addresses.
*/
TAILQ_HEAD(mibifa_list, mibifa);
enum {
MIBIFA_FOUND = 0x0001,
MIBIFA_DESTROYED = 0x0002,
};
/*
* Receive addresses
*/
TAILQ_HEAD(mibrcvaddr_list, mibrcvaddr);
enum {
MIBRCVADDR_FOUND = 0x00010000,
};
/*
* Interface index mapping. The problem here is, that if the same interface
* is reinstantiated (for examble by unloading and loading the hardware driver)
* we must use the same index for this interface. For dynamic interfaces
* (clip, lane) we must use a fresh index, each time a new interface is created.
* To differentiate between these types of interfaces we use the following table
* which contains an entry for each dynamic interface type. All other interface
* types are supposed to be static. The mibindexmap contains an entry for
* all interfaces. The mibif pointer is NULL, if the interface doesn't exist
* anymore.
*/
struct mibdynif {
SLIST_ENTRY(mibdynif) link;
char name[IFNAMSIZ];
};
SLIST_HEAD(mibdynif_list, mibdynif);
struct mibindexmap {
STAILQ_ENTRY(mibindexmap) link;
u_short sysindex;
u_int ifindex;
struct mibif *mibif; /* may be NULL */
char name[IFNAMSIZ];
};
STAILQ_HEAD(mibindexmap_list, mibindexmap);
/*
* Interface stacking. The generic code cannot know how the interfaces stack.
* For this reason it instantiates only the x.0 and 0.x table elements. All
* others have to be instantiated by the interface specific modules.
* The table is read-only.
*/
struct mibifstack {
TAILQ_ENTRY(mibifstack) link;
struct asn_oid index;
};
TAILQ_HEAD(mibifstack_list, mibifstack);
/*
* NetToMediaTable (ArpTable)
*/
struct mibarp {
TAILQ_ENTRY(mibarp) link;
struct asn_oid index; /* contains both the ifindex and addr */
u_char phys[128]; /* the physical address */
u_int physlen; /* and its length */
u_int flags;
};
TAILQ_HEAD(mibarp_list, mibarp);
enum {
MIBARP_FOUND = 0x00010000,
MIBARP_PERM = 0x00000001,
};
/*
* New if registrations
*/
struct newifreg {
TAILQ_ENTRY(newifreg) link;
const struct lmodule *mod;
int (*func)(struct mibif *);
};
TAILQ_HEAD(newifreg_list, newifreg);
/* list of all IP addresses */
extern struct mibifa_list mibifa_list;
/* list of all interfaces */
extern struct mibif_list mibif_list;
/* list of dynamic interface names */
extern struct mibdynif_list mibdynif_list;
/* list of all interface index mappings */
extern struct mibindexmap_list mibindexmap_list;
/* list of all stacking entries */
extern struct mibifstack_list mibifstack_list;
/* list of all receive addresses */
extern struct mibrcvaddr_list mibrcvaddr_list;
/* list of all NetToMedia entries */
extern struct mibarp_list mibarp_list;
/* number of interfaces */
extern int32_t mib_if_number;
/* last change of interface table */
extern u_int32_t mib_iftable_last_change;
/* last change of stack table */
extern u_int32_t mib_ifstack_last_change;
/* if this is set, one of our lists may be bad. refresh them when idle */
extern int mib_iflist_bad;
/* last time refreshed */
extern u_int32_t mibarpticks;
/* info on system clocks */
extern struct clockinfo clockinfo;
/* get interfaces and interface addresses. */
void mib_fetch_interfaces(void);
/* check whether this interface(type) is dynamic */
int mib_if_is_dyn(const char *name);
/* destroy an interface address */
int mib_destroy_ifa(struct mibifa *);
/* restituate a deleted interface address */
void mib_undestroy_ifa(struct mibifa *);
/* change interface address */
int mib_modify_ifa(struct mibifa *);
/* undo if address modification */
void mib_unmodify_ifa(struct mibifa *);
/* create an interface address */
struct mibifa * mib_create_ifa(u_int ifindex, struct in_addr addr, struct in_addr mask, struct in_addr bcast);
/* delete a freshly created address */
void mib_uncreate_ifa(struct mibifa *);
/* create/delete arp entries */
struct mibarp *mib_arp_create(const struct mibif *, struct in_addr, const u_char *, size_t);
void mib_arp_delete(struct mibarp *);
/* find arp entry */
struct mibarp *mib_find_arp(const struct mibif *, struct in_addr);
/* update arp table */
void mib_arp_update(void);
/* fetch routing table */
u_char *mib_fetch_rtab(int af, int info, int arg, size_t *lenp);
/* extract addresses from routing message */
void mib_extract_addrs(int, u_char *, struct sockaddr **);

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/snmp_mibII/mibII_ifmib.c,v 1.7 2003/01/28 13:44:35 hbb Exp $
*
* Interfaces group.
*/
#include "mibII.h"
#include "mibII_oid.h"
/*
* Scalars
*/
int
op_ifmib(struct snmp_context *ctx __unused, struct snmp_value *value,
u_int sub, u_int idx __unused, enum snmp_op op)
{
switch (op) {
case SNMP_OP_GETNEXT:
abort();
case SNMP_OP_GET:
break;
case SNMP_OP_SET:
return (SNMP_ERR_NOT_WRITEABLE);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
abort();
}
switch (value->var.subs[sub - 1]) {
case LEAF_ifTableLastChange:
if (mib_iftable_last_change > start_tick)
value->v.uint32 = mib_iftable_last_change - start_tick;
else
value->v.uint32 = 0;
break;
case LEAF_ifStackLastChange:
if (mib_ifstack_last_change > start_tick)
value->v.uint32 = mib_ifstack_last_change - start_tick;
else
value->v.uint32 = 0;
break;
}
return (SNMP_ERR_NOERROR);
}

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/snmp_mibII/mibII_ifstack.c,v 1.5 2003/01/28 13:44:35 hbb Exp $
*
* ifStackTable. Read-only.
*/
#include "mibII.h"
int
mib_ifstack_create(const struct mibif *lower, const struct mibif *upper)
{
struct mibifstack *stack;
if ((stack = malloc(sizeof(*stack))) == NULL)
return (-1);
stack->index.len = 2;
stack->index.subs[0] = upper ? upper->index : 0;
stack->index.subs[1] = lower ? lower->index : 0;
INSERT_OBJECT_OID(stack, &mibifstack_list);
mib_ifstack_last_change = get_ticks();
return (0);
}
void
mib_ifstack_delete(const struct mibif *lower, const struct mibif *upper)
{
struct mibifstack *stack;
TAILQ_FOREACH(stack, &mibifstack_list, link)
if (stack->index.subs[0] == (upper ? upper->index : 0) &&
stack->index.subs[1] == (lower ? lower->index : 0)) {
TAILQ_REMOVE(&mibifstack_list, stack, link);
free(stack);
mib_ifstack_last_change = get_ticks();
return;
}
}
int
op_ifstack(struct snmp_context *ctx __unused, struct snmp_value *value,
u_int sub, u_int iidx __unused, enum snmp_op op)
{
struct mibifstack *stack;
switch (op) {
case SNMP_OP_GETNEXT:
if ((stack = NEXT_OBJECT_OID(&mibifstack_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NOSUCHNAME);
index_append(&value->var, sub, &stack->index);
break;
case SNMP_OP_GET:
if ((stack = FIND_OBJECT_OID(&mibifstack_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NOSUCHNAME);
break;
case SNMP_OP_SET:
if ((stack = FIND_OBJECT_OID(&mibifstack_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NO_CREATION);
return (SNMP_ERR_NOT_WRITEABLE);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
abort();
}
switch (value->var.subs[sub - 1]) {
case LEAF_ifStackStatus:
value->v.integer = 1;
break;
}
return (SNMP_ERR_NOERROR);
}

View File

@ -0,0 +1,524 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/snmp_mibII/mibII_interfaces.c,v 1.9 2003/01/28 13:44:35 hbb Exp $
*
* Interfaces group.
*/
#include "mibII.h"
#include "mibII_oid.h"
/*
* This structure catches all changes to a interface entry
*/
struct ifchange {
struct snmp_dependency dep;
u_int ifindex;
u_int32_t set;
int promisc;
int admin;
int traps;
u_int32_t rb;
int rb_flags;
int rb_traps;
};
#define IFC_PROMISC 0x0001
#define IFC_ADMIN 0x0002
#define IFC_TRAPS 0x0004
#define IFRB_FLAGS 0x0001
#define IFRB_TRAPS 0x0002
static const struct asn_oid
oid_ifTable = OIDX_ifTable;
/*
* This function handles all changes to the interface table and interface
* extension table.
*/
static int
ifchange_func(struct snmp_context *ctx __unused, struct snmp_dependency *dep,
enum snmp_depop op)
{
struct ifchange *ifc = (struct ifchange *)dep;
struct mibif *ifp;
struct ifreq ifr, ifr1;
if ((ifp = mib_find_if(ifc->ifindex)) == NULL)
return (SNMP_ERR_NO_CREATION);
switch (op) {
case SNMP_DEPOP_COMMIT:
strncpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr) == -1) {
syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name);
return (SNMP_ERR_GENERR);
}
if (ifc->set & IFC_PROMISC) {
ifr.ifr_flags &= ~IFF_PROMISC;
if (ifc->promisc)
ifr.ifr_flags |= IFF_PROMISC;
ifc->rb |= IFRB_FLAGS;
}
if (ifc->set & IFC_ADMIN) {
ifr.ifr_flags &= ~IFF_UP;
if (ifc->admin)
ifr.ifr_flags |= IFF_UP;
ifc->rb |= IFRB_FLAGS;
}
if (ifc->rb & IFRB_FLAGS) {
strncpy(ifr1.ifr_name, ifp->name, sizeof(ifr1.ifr_name));
if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr1) == -1) {
syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name);
return (SNMP_ERR_GENERR);
}
ifc->rb_flags = ifr1.ifr_flags;
if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) {
syslog(LOG_ERR, "SIFFLAGS(%s): %m", ifp->name);
return (SNMP_ERR_GENERR);
}
(void)mib_fetch_ifmib(ifp);
}
if (ifc->set & IFC_TRAPS) {
ifc->rb |= IFRB_TRAPS;
ifc->rb_traps = ifp->trap_enable;
ifp->trap_enable = ifc->traps;
}
return (SNMP_ERR_NOERROR);
case SNMP_DEPOP_ROLLBACK:
if (ifc->rb & IFRB_FLAGS) {
strncpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
ifr.ifr_flags = ifc->rb_flags;
if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) {
syslog(LOG_ERR, "SIFFLAGS(%s): %m", ifp->name);
return (SNMP_ERR_UNDO_FAILED);
}
(void)mib_fetch_ifmib(ifp);
}
if (ifc->rb & IFRB_TRAPS)
ifp->trap_enable = ifc->rb_traps;
return (SNMP_ERR_NOERROR);
}
abort();
}
static u_int32_t
ticks_get_timeval(struct timeval *tv)
{
u_int32_t v;
if (tv->tv_sec != 0 || tv->tv_usec != 0) {
v = 100 * tv->tv_sec + tv->tv_usec / 10000;
if (v > start_tick)
return (v - start_tick);
}
return (0);
}
/*
* Scalars
*/
int
op_interfaces(struct snmp_context *ctx __unused, struct snmp_value *value,
u_int sub, u_int idx __unused, enum snmp_op op)
{
switch (op) {
case SNMP_OP_GETNEXT:
abort();
case SNMP_OP_GET:
break;
case SNMP_OP_SET:
return (SNMP_ERR_NOT_WRITEABLE);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
abort();
}
switch (value->var.subs[sub - 1]) {
case LEAF_ifNumber:
value->v.integer = mib_if_number;
break;
}
return (SNMP_ERR_NOERROR);
}
/*
* Iftable entry
*/
int
op_ifentry(struct snmp_context *ctx, struct snmp_value *value,
u_int sub, u_int iidx __unused, enum snmp_op op)
{
struct mibif *ifp = NULL;
int ret;
struct ifchange *ifc;
struct asn_oid idx;
switch (op) {
case SNMP_OP_GETNEXT:
if ((ifp = NEXT_OBJECT_INT(&mibif_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NOSUCHNAME);
value->var.len = sub + 1;
value->var.subs[sub] = ifp->index;
break;
case SNMP_OP_GET:
if (value->var.len - sub != 1)
return (SNMP_ERR_NOSUCHNAME);
if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
return (SNMP_ERR_NOSUCHNAME);
break;
case SNMP_OP_SET:
if (value->var.len - sub != 1)
return (SNMP_ERR_NO_CREATION);
if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
return (SNMP_ERR_NO_CREATION);
if (value->var.subs[sub - 1] != LEAF_ifAdminStatus)
return (SNMP_ERR_NOT_WRITEABLE);
idx.len = 1;
idx.subs[0] = ifp->index;
if (value->v.integer != 1 && value->v.integer != 2)
return (SNMP_ERR_WRONG_VALUE);
if ((ifc = (struct ifchange *)snmp_dep_lookup(ctx,
&oid_ifTable, &idx, sizeof(*ifc), ifchange_func)) == NULL)
return (SNMP_ERR_RES_UNAVAIL);
ifc->ifindex = ifp->index;
if (ifc->set & IFC_ADMIN)
return (SNMP_ERR_INCONS_VALUE);
ifc->set |= IFC_ADMIN;
ifc->admin = (value->v.integer == 1) ? 1 : 0;
return (SNMP_ERR_NOERROR);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
return (SNMP_ERR_NOERROR);
}
if (ifp->mibtick < this_tick)
(void)mib_fetch_ifmib(ifp);
ret = SNMP_ERR_NOERROR;
switch (value->var.subs[sub - 1]) {
case LEAF_ifIndex:
value->v.integer = ifp->index;
break;
case LEAF_ifDescr:
ret = string_get(value, ifp->descr, -1);
break;
case LEAF_ifType:
value->v.integer = ifp->mib.ifmd_data.ifi_type;
break;
case LEAF_ifMtu:
value->v.integer = ifp->mib.ifmd_data.ifi_mtu;
break;
case LEAF_ifSpeed:
value->v.integer = ifp->mib.ifmd_data.ifi_baudrate;
break;
case LEAF_ifPhysAddress:
ret = string_get(value, ifp->physaddr,
ifp->physaddrlen);
break;
case LEAF_ifAdminStatus:
value->v.integer =
(ifp->mib.ifmd_flags & IFF_UP) ? 1 : 2;
break;
case LEAF_ifOperStatus:
value->v.integer =
(ifp->mib.ifmd_flags & IFF_RUNNING) ? 1 : 2;
break;
case LEAF_ifLastChange:
value->v.uint32 =
ticks_get_timeval(&ifp->mib.ifmd_data.ifi_lastchange);
break;
case LEAF_ifInOctets:
value->v.uint32 = ifp->mib.ifmd_data.ifi_ibytes;
break;
case LEAF_ifInUcastPkts:
value->v.uint32 = ifp->mib.ifmd_data.ifi_ipackets -
ifp->mib.ifmd_data.ifi_imcasts;
break;
case LEAF_ifInNUcastPkts:
value->v.uint32 = ifp->mib.ifmd_data.ifi_imcasts;
break;
case LEAF_ifInDiscards:
value->v.uint32 = ifp->mib.ifmd_data.ifi_iqdrops;
break;
case LEAF_ifInErrors:
value->v.uint32 = ifp->mib.ifmd_data.ifi_ierrors;
break;
case LEAF_ifInUnknownProtos:
value->v.uint32 = ifp->mib.ifmd_data.ifi_noproto;
break;
case LEAF_ifOutOctets:
value->v.uint32 = ifp->mib.ifmd_data.ifi_obytes;
break;
case LEAF_ifOutUcastPkts:
value->v.uint32 = ifp->mib.ifmd_data.ifi_opackets -
ifp->mib.ifmd_data.ifi_omcasts;
break;
case LEAF_ifOutNUcastPkts:
value->v.uint32 = ifp->mib.ifmd_data.ifi_omcasts;
break;
case LEAF_ifOutDiscards:
value->v.uint32 = ifp->mib.ifmd_snd_drops;
break;
case LEAF_ifOutErrors:
value->v.uint32 = ifp->mib.ifmd_data.ifi_oerrors;
break;
case LEAF_ifOutQLen:
value->v.uint32 = ifp->mib.ifmd_snd_len;
break;
case LEAF_ifSpecific:
value->v.oid = oid_zeroDotZero;
break;
}
return (SNMP_ERR_NOERROR);
}
/*
* IfXtable entry
*/
int
op_ifxtable(struct snmp_context *ctx, struct snmp_value *value,
u_int sub, u_int iidx __unused, enum snmp_op op)
{
struct mibif *ifp = NULL;
int ret;
struct ifchange *ifc;
struct asn_oid idx;
switch (op) {
again:
if (op != SNMP_OP_GETNEXT)
return (SNMP_ERR_NOSUCHNAME);
/* FALLTHROUGH */
case SNMP_OP_GETNEXT:
if ((ifp = NEXT_OBJECT_INT(&mibif_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NOSUCHNAME);
value->var.len = sub + 1;
value->var.subs[sub] = ifp->index;
break;
case SNMP_OP_GET:
if (value->var.len - sub != 1)
return (SNMP_ERR_NOSUCHNAME);
if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
return (SNMP_ERR_NOSUCHNAME);
break;
case SNMP_OP_SET:
if (value->var.len - sub != 1)
return (SNMP_ERR_NO_CREATION);
if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
return (SNMP_ERR_NO_CREATION);
idx.len = 1;
idx.subs[0] = ifp->index;
if ((ifc = (struct ifchange *)snmp_dep_lookup(ctx,
&oid_ifTable, &idx, sizeof(*ifc), ifchange_func)) == NULL)
return (SNMP_ERR_RES_UNAVAIL);
ifc->ifindex = ifp->index;
switch (value->var.subs[sub - 1]) {
case LEAF_ifLinkUpDownTrapEnable:
if (value->v.integer != 1 && value->v.integer != 2)
return (SNMP_ERR_WRONG_VALUE);
if (ifc->set & IFC_TRAPS)
return (SNMP_ERR_INCONS_VALUE);
ifc->set |= IFC_TRAPS;
ifc->traps = (value->v.integer == 1) ? 1 : 0;
return (SNMP_ERR_NOERROR);
case LEAF_ifPromiscuousMode:
if (value->v.integer != 1 && value->v.integer != 2)
return (SNMP_ERR_WRONG_VALUE);
if (ifc->set & IFC_PROMISC)
return (SNMP_ERR_INCONS_VALUE);
ifc->set |= IFC_PROMISC;
ifc->promisc = (value->v.integer == 1) ? 1 : 0;
return (SNMP_ERR_NOERROR);
}
return (SNMP_ERR_NOT_WRITEABLE);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
return (SNMP_ERR_NOERROR);
}
if (ifp->mibtick < this_tick)
(void)mib_fetch_ifmib(ifp);
ret = SNMP_ERR_NOERROR;
switch (value->var.subs[sub - 1]) {
case LEAF_ifName:
ret = string_get(value, ifp->name, -1);
break;
case LEAF_ifInMulticastPkts:
value->v.uint32 = ifp->mib.ifmd_data.ifi_imcasts;
break;
case LEAF_ifInBroadcastPkts:
value->v.uint32 = 0;
break;
case LEAF_ifOutMulticastPkts:
value->v.uint32 = ifp->mib.ifmd_data.ifi_omcasts;
break;
case LEAF_ifOutBroadcastPkts:
value->v.uint32 = 0;
break;
case LEAF_ifHCInOctets:
if (!(ifp->flags & MIBIF_HIGHSPEED))
goto again;
value->v.counter64 = ifp->hc_inoctets;
break;
case LEAF_ifHCInUcastPkts:
if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
goto again;
value->v.counter64 = ifp->hc_ipackets - ifp->hc_imcasts;
break;
case LEAF_ifHCInMulticastPkts:
if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
goto again;
value->v.counter64 = ifp->hc_imcasts;
break;
case LEAF_ifHCInBroadcastPkts:
if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
goto again;
value->v.counter64 = 0;
break;
case LEAF_ifHCOutOctets:
if (!(ifp->flags & MIBIF_HIGHSPEED))
goto again;
value->v.counter64 = ifp->hc_inoctets;
break;
case LEAF_ifHCOutUcastPkts:
if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
goto again;
value->v.counter64 = ifp->hc_opackets - ifp->hc_omcasts;
break;
case LEAF_ifHCOutMulticastPkts:
if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
goto again;
value->v.counter64 = ifp->hc_omcasts;
break;
case LEAF_ifHCOutBroadcastPkts:
if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
goto again;
value->v.counter64 = 0;
break;
case LEAF_ifLinkUpDownTrapEnable:
value->v.integer = ifp->trap_enable ? 1 : 2;
break;
case LEAF_ifHighSpeed:
value->v.integer =
(ifp->mib.ifmd_data.ifi_baudrate + 499999) / 1000000;
break;
case LEAF_ifPromiscuousMode:
value->v.integer =
(ifp->mib.ifmd_flags & IFF_PROMISC) ? 1 : 2;
break;
case LEAF_ifConnectorPresent:
value->v.integer = ifp->has_connector ? 1 : 2;
break;
case LEAF_ifAlias:
ret = string_get(value, "", -1);
break;
case LEAF_ifCounterDiscontinuityTime:
if (ifp->counter_disc > start_tick)
value->v.uint32 = ifp->counter_disc - start_tick;
else
value->v.uint32 = 0;
break;
}
return (ret);
}

View File

@ -0,0 +1,497 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/snmp_mibII/mibII_ip.c,v 1.8 2003/01/28 13:44:35 hbb Exp $
*
* ip group scalars.
*/
#include "mibII.h"
#include "mibII_oid.h"
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/ip_icmp.h>
#include <netinet/icmp_var.h>
static struct ipstat ipstat;
static u_int ip_idrop;
static struct icmpstat icmpstat;
static int ip_forwarding;
static int ip_defttl;
static u_int32_t ip_tick;
static u_int32_t ipstat_tick;
static int
fetch_ipstat(void)
{
size_t len;
len = sizeof(ipstat);
if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, NULL, 0) == -1) {
syslog(LOG_ERR, "net.inet.ip.stats: %m");
return (-1);
}
if (len != sizeof(ipstat)) {
syslog(LOG_ERR, "net.inet.ip.stats: wrong size");
return (-1);
}
len = sizeof(ip_idrop);
if (sysctlbyname("net.inet.ip.intr_queue_drops", &ip_idrop, &len, NULL, 0) == -1)
syslog(LOG_WARNING, "net.inet.ip.intr_queue_drops: %m");
if (len != sizeof(ip_idrop)) {
syslog(LOG_WARNING, "net.inet.ip.intr_queue_drops: wrong size");
ip_idrop = 0;
}
len = sizeof(icmpstat);
if (sysctlbyname("net.inet.icmp.stats", &icmpstat, &len, NULL, 0) == -1) {
syslog(LOG_ERR, "net.inet.icmp.stats: %m");
return (-1);
}
if (len != sizeof(icmpstat)) {
syslog(LOG_ERR, "net.inet.icmp.stats: wrong size");
return (-1);
}
ipstat_tick = get_ticks();
return (0);
}
static int
fetch_ip(void)
{
size_t len;
len = sizeof(ip_forwarding);
if (sysctlbyname("net.inet.ip.forwarding", &ip_forwarding, &len,
NULL, 0) == -1) {
syslog(LOG_ERR, "net.inet.ip.forwarding: %m");
return (-1);
}
if (len != sizeof(ip_forwarding)) {
syslog(LOG_ERR, "net.inet.ip.forwarding: wrong size");
return (-1);
}
len = sizeof(ip_defttl);
if (sysctlbyname("net.inet.ip.ttl", &ip_defttl, &len,
NULL, 0) == -1) {
syslog(LOG_ERR, "net.inet.ip.ttl: %m");
return (-1);
}
if (len != sizeof(ip_defttl)) {
syslog(LOG_ERR, "net.inet.ip.ttl: wrong size");
return (-1);
}
ip_tick = get_ticks();
return (0);
}
static int
ip_forward(int forw, int *old)
{
size_t olen;
olen = sizeof(*old);
if (sysctlbyname("net.inet.ip.forwarding", old, old ? &olen : NULL,
&forw, sizeof(forw)) == -1) {
syslog(LOG_ERR, "set net.inet.ip.forwarding: %m");
return (-1);
}
ip_forwarding = forw;
return (0);
}
static int
ip_setttl(int ttl, int *old)
{
size_t olen;
olen = sizeof(*old);
if (sysctlbyname("net.inet.ip.ttl", old, old ? &olen : NULL,
&ttl, sizeof(ttl)) == -1) {
syslog(LOG_ERR, "set net.inet.ip.ttl: %m");
return (-1);
}
ip_defttl = ttl;
return (0);
}
/*
* READ/WRITE ip group.
*/
int
op_ip(struct snmp_context *ctx, struct snmp_value *value,
u_int sub, u_int idx __unused, enum snmp_op op)
{
int old;
switch (op) {
case SNMP_OP_GETNEXT:
abort();
case SNMP_OP_GET:
break;
case SNMP_OP_SET:
if (ip_tick < this_tick)
if (fetch_ip() == -1)
return (SNMP_ERR_GENERR);
switch (value->var.subs[sub - 1]) {
case LEAF_ipForwarding:
ctx->scratch->int1 = ip_forwarding ? 1 : 2;
ctx->scratch->int2 = value->v.integer;
if (value->v.integer == 1) {
if (!ip_forwarding && ip_forward(1, &old))
return (SNMP_ERR_GENERR);
ctx->scratch->int1 = old ? 1 : 2;
} else if (value->v.integer == 2) {
if (ip_forwarding && ip_forward(0, &old))
return (SNMP_ERR_GENERR);
ctx->scratch->int1 = old;
} else
return (SNMP_ERR_WRONG_VALUE);
break;
case LEAF_ipDefaultTTL:
ctx->scratch->int1 = ip_defttl;
ctx->scratch->int2 = value->v.integer;
if (value->v.integer < 1 || value->v.integer > 255)
return (SNMP_ERR_WRONG_VALUE);
if (ip_defttl != value->v.integer &&
ip_setttl(value->v.integer, &old))
return (SNMP_ERR_GENERR);
ctx->scratch->int1 = old;
break;
}
return (SNMP_ERR_NOERROR);
case SNMP_OP_ROLLBACK:
switch (value->var.subs[sub - 1]) {
case LEAF_ipForwarding:
if (ctx->scratch->int1 == 1) {
if (ctx->scratch->int2 == 2)
(void)ip_forward(1, NULL);
} else {
if (ctx->scratch->int2 == 1)
(void)ip_forward(0, NULL);
}
break;
case LEAF_ipDefaultTTL:
if (ctx->scratch->int1 != ctx->scratch->int2)
(void)ip_setttl(ctx->scratch->int1, NULL);
break;
}
return (SNMP_ERR_NOERROR);
case SNMP_OP_COMMIT:
return (SNMP_ERR_NOERROR);
}
if (ip_tick < this_tick)
if (fetch_ip() == -1)
return (SNMP_ERR_GENERR);
switch (value->var.subs[sub - 1]) {
case LEAF_ipForwarding:
value->v.integer = ip_forwarding ? 1 : 2;
break;
case LEAF_ipDefaultTTL:
value->v.integer = ip_defttl;
break;
}
return (SNMP_ERR_NOERROR);
}
/*
* READ-ONLY statistics ip group.
*/
int
op_ipstat(struct snmp_context *ctx __unused, struct snmp_value *value,
u_int sub, u_int idx __unused, enum snmp_op op)
{
switch (op) {
case SNMP_OP_GETNEXT:
abort();
case SNMP_OP_GET:
break;
case SNMP_OP_SET:
return (SNMP_ERR_NOT_WRITEABLE);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
abort();
}
if (ipstat_tick < this_tick)
fetch_ipstat();
switch (value->var.subs[sub - 1]) {
case LEAF_ipInReceives:
value->v.uint32 = ipstat.ips_total;
break;
case LEAF_ipInHdrErrors:
value->v.uint32 = ipstat.ips_badsum + ipstat.ips_tooshort
+ ipstat.ips_toosmall + ipstat.ips_badhlen
+ ipstat.ips_badlen + ipstat.ips_badvers +
+ ipstat.ips_toolong;
break;
case LEAF_ipInAddrErrors:
value->v.uint32 = ipstat.ips_cantforward;
break;
case LEAF_ipForwDatagrams:
value->v.uint32 = ipstat.ips_forward;
break;
case LEAF_ipInUnknownProtos:
value->v.uint32 = ipstat.ips_noproto;
break;
case LEAF_ipInDiscards:
value->v.uint32 = ip_idrop;
break;
case LEAF_ipInDelivers:
value->v.uint32 = ipstat.ips_delivered;
break;
case LEAF_ipOutRequests:
value->v.uint32 = ipstat.ips_localout;
break;
case LEAF_ipOutDiscards:
value->v.uint32 = ipstat.ips_odropped;
break;
case LEAF_ipOutNoRoutes:
value->v.uint32 = ipstat.ips_noroute;
break;
case LEAF_ipReasmTimeout:
value->v.integer = IPFRAGTTL;
break;
case LEAF_ipReasmReqds:
value->v.uint32 = ipstat.ips_fragments;
break;
case LEAF_ipReasmOKs:
value->v.uint32 = ipstat.ips_reassembled;
break;
case LEAF_ipReasmFails:
value->v.uint32 = ipstat.ips_fragdropped
+ ipstat.ips_fragtimeout;
break;
case LEAF_ipFragOKs:
value->v.uint32 = ipstat.ips_fragmented;
break;
case LEAF_ipFragFails:
value->v.uint32 = ipstat.ips_cantfrag;
break;
case LEAF_ipFragCreates:
value->v.uint32 = ipstat.ips_ofragments;
break;
}
return (SNMP_ERR_NOERROR);
}
/*
* READ-ONLY statistics icmp group.
*/
int
op_icmpstat(struct snmp_context *ctx __unused, struct snmp_value *value,
u_int sub, u_int idx __unused, enum snmp_op op)
{
u_int i;
switch (op) {
case SNMP_OP_GETNEXT:
abort();
case SNMP_OP_GET:
break;
case SNMP_OP_SET:
return (SNMP_ERR_NOT_WRITEABLE);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
abort();
}
if (ipstat_tick < this_tick)
fetch_ipstat();
switch (value->var.subs[sub - 1]) {
case LEAF_icmpInMsgs:
value->v.integer = 0;
for (i = 0; i <= ICMP_MAXTYPE; i++)
value->v.integer += icmpstat.icps_inhist[i];
value->v.integer += icmpstat.icps_tooshort +
icmpstat.icps_checksum;
/* missing: bad type and packets on faith */
break;
case LEAF_icmpInErrors:
value->v.integer = icmpstat.icps_tooshort +
icmpstat.icps_checksum +
icmpstat.icps_badlen +
icmpstat.icps_badcode +
icmpstat.icps_bmcastecho +
icmpstat.icps_bmcasttstamp;
break;
case LEAF_icmpInDestUnreachs:
value->v.integer = icmpstat.icps_inhist[ICMP_UNREACH];
break;
case LEAF_icmpInTimeExcds:
value->v.integer = icmpstat.icps_inhist[ICMP_TIMXCEED];
break;
case LEAF_icmpInParmProbs:
value->v.integer = icmpstat.icps_inhist[ICMP_PARAMPROB];
break;
case LEAF_icmpInSrcQuenchs:
value->v.integer = icmpstat.icps_inhist[ICMP_SOURCEQUENCH];
break;
case LEAF_icmpInRedirects:
value->v.integer = icmpstat.icps_inhist[ICMP_REDIRECT];
break;
case LEAF_icmpInEchos:
value->v.integer = icmpstat.icps_inhist[ICMP_ECHO];
break;
case LEAF_icmpInEchoReps:
value->v.integer = icmpstat.icps_inhist[ICMP_ECHOREPLY];
break;
case LEAF_icmpInTimestamps:
value->v.integer = icmpstat.icps_inhist[ICMP_TSTAMP];
break;
case LEAF_icmpInTimestampReps:
value->v.integer = icmpstat.icps_inhist[ICMP_TSTAMPREPLY];
break;
case LEAF_icmpInAddrMasks:
value->v.integer = icmpstat.icps_inhist[ICMP_MASKREQ];
break;
case LEAF_icmpInAddrMaskReps:
value->v.integer = icmpstat.icps_inhist[ICMP_MASKREPLY];
break;
case LEAF_icmpOutMsgs:
value->v.integer = 0;
for (i = 0; i <= ICMP_MAXTYPE; i++)
value->v.integer += icmpstat.icps_outhist[i];
value->v.integer += icmpstat.icps_badaddr +
icmpstat.icps_noroute;
break;
case LEAF_icmpOutErrors:
value->v.integer = icmpstat.icps_badaddr +
icmpstat.icps_noroute;
break;
case LEAF_icmpOutDestUnreachs:
value->v.integer = icmpstat.icps_outhist[ICMP_UNREACH];
break;
case LEAF_icmpOutTimeExcds:
value->v.integer = icmpstat.icps_outhist[ICMP_TIMXCEED];
break;
case LEAF_icmpOutParmProbs:
value->v.integer = icmpstat.icps_outhist[ICMP_PARAMPROB];
break;
case LEAF_icmpOutSrcQuenchs:
value->v.integer = icmpstat.icps_outhist[ICMP_SOURCEQUENCH];
break;
case LEAF_icmpOutRedirects:
value->v.integer = icmpstat.icps_outhist[ICMP_REDIRECT];
break;
case LEAF_icmpOutEchos:
value->v.integer = icmpstat.icps_outhist[ICMP_ECHO];
break;
case LEAF_icmpOutEchoReps:
value->v.integer = icmpstat.icps_outhist[ICMP_ECHOREPLY];
break;
case LEAF_icmpOutTimestamps:
value->v.integer = icmpstat.icps_outhist[ICMP_TSTAMP];
break;
case LEAF_icmpOutTimestampReps:
value->v.integer = icmpstat.icps_outhist[ICMP_TSTAMPREPLY];
break;
case LEAF_icmpOutAddrMasks:
value->v.integer = icmpstat.icps_outhist[ICMP_MASKREQ];
break;
case LEAF_icmpOutAddrMaskReps:
value->v.integer = icmpstat.icps_outhist[ICMP_MASKREPLY];
break;
}
return (SNMP_ERR_NOERROR);
}

View File

@ -0,0 +1,351 @@
/*
* Copyright (c) 2001-2002
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/snmp_mibII/mibII_ipaddr.c,v 1.6 2003/01/28 13:44:35 hbb Exp $
*
* IP address table. This table is writeable!
*
* Writing to this table will add a new IP address to the interface.
* An address can be deleted with writing the interface index 0.
*/
#include "mibII.h"
#include "mibII_oid.h"
static const struct asn_oid
oid_ipAddrTable = OIDX_ipAddrTable;
/*
* Be careful not to hold any pointers during the SET processing - the
* interface and address lists can be relocated at any time.
*/
struct update {
struct snmp_dependency dep;
u_int32_t set;
struct in_addr addr;
struct in_addr mask;
int bcast;
u_int ifindex;
u_int32_t rb;
struct in_addr rb_mask;
struct in_addr rb_bcast;
};
#define UPD_IFINDEX 0x0001
#define UPD_MASK 0x0002
#define UPD_BCAST 0x0004
#define RB_CREATE 0x0001
#define RB_DESTROY 0x0002
#define RB_MODIFY 0x0004
/*
* Create a new interface address
*/
static int
create(struct update *upd)
{
struct in_addr bcast;
struct mibifa *ifa;
if (!(upd->set & UPD_MASK)) {
if (IN_CLASSA(ntohl(upd->addr.s_addr)))
upd->mask.s_addr = htonl(IN_CLASSA_NET);
else if (IN_CLASSB(ntohl(upd->addr.s_addr)))
upd->mask.s_addr = htonl(IN_CLASSB_NET);
else if (IN_CLASSC(ntohl(upd->addr.s_addr)))
upd->mask.s_addr = htonl(IN_CLASSC_NET);
else
upd->mask.s_addr = 0xffffffff;
}
bcast.s_addr = upd->addr.s_addr & upd->mask.s_addr;
if (!(upd->set & UPD_BCAST) || upd->bcast)
bcast.s_addr |= htonl(0xffffffff & ~ntohl(upd->mask.s_addr));
if ((ifa = mib_create_ifa(upd->ifindex, upd->addr, upd->mask, bcast)) == NULL)
return (SNMP_ERR_GENERR);
upd->rb |= RB_CREATE;
return (SNMP_ERR_NOERROR);
}
/*
* Modify the netmask or broadcast address. The ifindex cannot be
* changed (obviously).
*/
static int
modify(struct update *upd, struct mibifa *ifa)
{
struct mibif *ifp;
if ((ifp = mib_find_if(ifa->ifindex)) == NULL)
return (SNMP_ERR_WRONG_VALUE);
if ((upd->set & UPD_IFINDEX) && upd->ifindex != ifa->ifindex)
return (SNMP_ERR_INCONS_VALUE);
upd->rb_mask = ifa->inmask;
upd->rb_bcast = ifa->inbcast;
if (((upd->set & UPD_MASK) && upd->mask.s_addr != ifa->inmask.s_addr) ||
(upd->set & UPD_BCAST)) {
if (upd->set & UPD_MASK)
ifa->inmask = upd->mask;
if (upd->set & UPD_BCAST) {
ifa->inbcast.s_addr = ifa->inaddr.s_addr
& ifa->inmask.s_addr;
if (upd->bcast)
ifa->inbcast.s_addr |= 0xffffffff
& ~ifa->inmask.s_addr;
}
if (mib_modify_ifa(ifa)) {
syslog(LOG_ERR, "set netmask/bcast: %m");
ifa->inmask = upd->rb_mask;
ifa->inbcast = upd->rb_bcast;
mib_unmodify_ifa(ifa);
return (SNMP_ERR_GENERR);
}
upd->rb |= RB_MODIFY;
}
return (SNMP_ERR_NOERROR);
}
/*
* Remove an IP address from an interface. This is called when
* the SET finishes.
*/
static void
destroy_func(struct snmp_context *ctx __unused, int fail __unused, void *arg)
{
struct mibifa *ifa = arg;
if (ifa->flags & MIBIFA_DESTROYED) {
TAILQ_REMOVE(&mibifa_list, ifa, link);
free(ifa);
}
}
/*
* Destroy the given row in the table. We remove the address from the
* system, but keep the structure around for the COMMIT. It's deleted
* only in the finish function.
*/
static int
destroy(struct snmp_context *ctx, struct update *upd, struct mibifa *ifa)
{
if (mib_destroy_ifa(ifa))
return (SNMP_ERR_GENERR);
if (snmp_set_atfinish(ctx, destroy_func, ifa)) {
syslog(LOG_ERR, "atfinish: %m");
mib_undestroy_ifa(ifa);
return (SNMP_ERR_GENERR);
}
upd->rb |= RB_DESTROY;
return (SNMP_ERR_NOERROR);
}
/*
* This function is called to commit/rollback a SET on an IpAddrEntry
*/
static int
update_func(struct snmp_context *ctx, struct snmp_dependency *dep,
enum snmp_depop op)
{
struct update *upd = (struct update *)dep;
struct mibifa *ifa;
switch (op) {
case SNMP_DEPOP_COMMIT:
if ((ifa = mib_find_ifa(upd->addr)) == NULL) {
/* non existing entry - must have ifindex */
if (!(upd->set & UPD_IFINDEX))
return (SNMP_ERR_INCONS_NAME);
return (create(upd));
}
/* existing entry */
if ((upd->set & UPD_IFINDEX) && upd->ifindex == 0) {
/* delete */
return (destroy(ctx, upd, ifa));
}
/* modify entry */
return (modify(upd, ifa));
case SNMP_DEPOP_ROLLBACK:
if ((ifa = mib_find_ifa(upd->addr)) == NULL) {
/* ups */
mib_iflist_bad = 1;
return (SNMP_ERR_NOERROR);
}
if (upd->rb & RB_CREATE) {
mib_uncreate_ifa(ifa);
return (SNMP_ERR_NOERROR);
}
if (upd->rb & RB_DESTROY) {
mib_undestroy_ifa(ifa);
return (SNMP_ERR_NOERROR);
}
if (upd->rb & RB_MODIFY) {
ifa->inmask = upd->rb_mask;
ifa->inbcast = upd->rb_bcast;
mib_unmodify_ifa(ifa);
return (SNMP_ERR_NOERROR);
}
return (SNMP_ERR_NOERROR);
}
abort();
}
/**********************************************************************/
/*
* ACTION
*/
int
op_ipaddr(struct snmp_context *ctx, struct snmp_value *value,
u_int sub, u_int iidx, enum snmp_op op)
{
asn_subid_t which;
struct mibifa *ifa;
struct update *upd;
struct asn_oid idx;
u_char ipaddr[4];
which = value->var.subs[sub - 1];
ifa = NULL;
switch (op) {
case SNMP_OP_GETNEXT:
if ((ifa = NEXT_OBJECT_OID(&mibifa_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NOSUCHNAME);
index_append(&value->var, sub, &ifa->index);
break;
case SNMP_OP_GET:
if ((ifa = FIND_OBJECT_OID(&mibifa_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NOSUCHNAME);
break;
case SNMP_OP_SET:
if (index_decode(&value->var, sub, iidx, ipaddr))
return (SNMP_ERR_NO_CREATION);
ifa = FIND_OBJECT_OID(&mibifa_list, &value->var, sub);
idx.len = 4;
idx.subs[0] = ipaddr[0];
idx.subs[1] = ipaddr[1];
idx.subs[2] = ipaddr[2];
idx.subs[3] = ipaddr[3];
if ((upd = (struct update *)snmp_dep_lookup(ctx,
&oid_ipAddrTable, &idx, sizeof(*upd), update_func)) == NULL)
return (SNMP_ERR_RES_UNAVAIL);
upd->addr.s_addr = htonl((ipaddr[0] << 24) | (ipaddr[1] << 16) |
(ipaddr[2] << 8) | (ipaddr[3] << 0));
switch (which) {
case LEAF_ipAdEntIfIndex:
if (upd->set & UPD_IFINDEX)
return (SNMP_ERR_INCONS_VALUE);
if (value->v.integer < 0 ||
value->v.integer > 0x07fffffff)
return (SNMP_ERR_WRONG_VALUE);
if (ifa != NULL) {
if (ifa->ifindex != (u_int)value->v.integer &&
value->v.integer != 0)
return (SNMP_ERR_INCONS_VALUE);
}
upd->set |= UPD_IFINDEX;
upd->ifindex = (u_int)value->v.integer;
break;
case LEAF_ipAdEntNetMask:
if (upd->set & UPD_MASK)
return (SNMP_ERR_INCONS_VALUE);
upd->mask.s_addr = htonl((value->v.ipaddress[0] << 24)
| (value->v.ipaddress[1] << 16)
| (value->v.ipaddress[2] << 8)
| (value->v.ipaddress[3] << 0));
upd->set |= UPD_MASK;
break;
case LEAF_ipAdEntBcastAddr:
if (upd->set & UPD_BCAST)
return (SNMP_ERR_INCONS_VALUE);
if (value->v.integer != 0 && value->v.integer != 1)
return (SNMP_ERR_WRONG_VALUE);
upd->bcast = value->v.integer;
upd->set |= UPD_BCAST;
break;
}
return (SNMP_ERR_NOERROR);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
return (SNMP_ERR_NOERROR);
}
switch (which) {
case LEAF_ipAdEntAddr:
value->v.ipaddress[0] = ifa->index.subs[0];
value->v.ipaddress[1] = ifa->index.subs[1];
value->v.ipaddress[2] = ifa->index.subs[2];
value->v.ipaddress[3] = ifa->index.subs[3];
break;
case LEAF_ipAdEntIfIndex:
if (ifa->flags & MIBIFA_DESTROYED)
value->v.integer = 0;
else
value->v.integer = ifa->ifindex;
break;
case LEAF_ipAdEntNetMask:
value->v.ipaddress[0] = (ntohl(ifa->inmask.s_addr) >> 24) & 0xff;
value->v.ipaddress[1] = (ntohl(ifa->inmask.s_addr) >> 16) & 0xff;
value->v.ipaddress[2] = (ntohl(ifa->inmask.s_addr) >> 8) & 0xff;
value->v.ipaddress[3] = (ntohl(ifa->inmask.s_addr) >> 0) & 0xff;
break;
case LEAF_ipAdEntBcastAddr:
value->v.integer = ntohl(ifa->inbcast.s_addr) & 1;
break;
case LEAF_ipAdEntReasmMaxSize:
value->v.integer = 65535;
break;
}
return (SNMP_ERR_NOERROR);
}

View File

@ -0,0 +1,154 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/snmp_mibII/mibII_nettomedia.c,v 1.6 2003/01/28 13:44:35 hbb Exp $
*
* Read-only implementation of the Arp table (ipNetToMediaTable)
*
* The problem with the table is, that we don't receive routing message
* when a) an arp table entry is resolved and b) when an arp table entry is
* deleted automatically. Therefor we need to poll the table from time to
* time.
*/
#include "mibII.h"
#include "mibII_oid.h"
#define ARPREFRESH 30
struct mibarp *
mib_find_arp(const struct mibif *ifp, struct in_addr in)
{
struct mibarp *at;
u_int32_t a = ntohl(in.s_addr);
if (get_ticks() >= mibarpticks + ARPREFRESH)
mib_arp_update();
TAILQ_FOREACH(at, &mibarp_list, link)
if (at->index.subs[0] == ifp->index &&
(at->index.subs[1] == ((a >> 24) & 0xff)) &&
(at->index.subs[2] == ((a >> 16) & 0xff)) &&
(at->index.subs[3] == ((a >> 8) & 0xff)) &&
(at->index.subs[4] == ((a >> 0) & 0xff)))
return (at);
return (NULL);
}
struct mibarp *
mib_arp_create(const struct mibif *ifp, struct in_addr in, const u_char *phys,
size_t physlen)
{
struct mibarp *at;
u_int32_t a = ntohl(in.s_addr);
if ((at = malloc(sizeof(*at))) == NULL)
return (NULL);
at->flags = 0;
at->index.len = 5;
at->index.subs[0] = ifp->index;
at->index.subs[1] = (a >> 24) & 0xff;
at->index.subs[2] = (a >> 16) & 0xff;
at->index.subs[3] = (a >> 8) & 0xff;
at->index.subs[4] = (a >> 0) & 0xff;
if ((at->physlen = physlen) > sizeof(at->phys))
at->physlen = sizeof(at->phys);
memcpy(at->phys, phys, at->physlen);
INSERT_OBJECT_OID(at, &mibarp_list);
return (at);
}
void
mib_arp_delete(struct mibarp *at)
{
TAILQ_REMOVE(&mibarp_list, at, link);
free(at);
}
int
op_nettomedia(struct snmp_context *ctx __unused, struct snmp_value *value,
u_int sub, u_int iidx __unused, enum snmp_op op)
{
struct mibarp *at;
at = NULL; /* gcc */
if (get_ticks() >= mibarpticks + ARPREFRESH)
mib_arp_update();
switch (op) {
case SNMP_OP_GETNEXT:
if ((at = NEXT_OBJECT_OID(&mibarp_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NOSUCHNAME);
index_append(&value->var, sub, &at->index);
break;
case SNMP_OP_GET:
if ((at = FIND_OBJECT_OID(&mibarp_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NOSUCHNAME);
break;
case SNMP_OP_SET:
if ((at = FIND_OBJECT_OID(&mibarp_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NO_CREATION);
return (SNMP_ERR_NOT_WRITEABLE);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
abort();
}
switch (value->var.subs[sub - 1]) {
case LEAF_ipNetToMediaIfIndex:
value->v.integer = at->index.subs[0];
break;
case LEAF_ipNetToMediaPhysAddress:
return (string_get(value, at->phys, at->physlen));
case LEAF_ipNetToMediaNetAddress:
value->v.ipaddress[0] = at->index.subs[1];
value->v.ipaddress[1] = at->index.subs[2];
value->v.ipaddress[2] = at->index.subs[3];
value->v.ipaddress[3] = at->index.subs[4];
break;
case LEAF_ipNetToMediaType:
value->v.integer = (at->flags & MIBARP_PERM) ? 4 : 3;
break;
}
return (SNMP_ERR_NOERROR);
}

View File

@ -0,0 +1,138 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/snmp_mibII/mibII_rcvaddr.c,v 1.7 2003/01/28 13:44:35 hbb Exp $
*
* Interface receive address table.
*/
#include "mibII.h"
#include "mibII_oid.h"
/*
* find receive address
*/
struct mibrcvaddr *
mib_find_rcvaddr(u_int ifindex, const u_char *addr, size_t addrlen)
{
struct mibrcvaddr *rcv;
TAILQ_FOREACH(rcv, &mibrcvaddr_list, link)
if (rcv->ifindex == ifindex &&
rcv->addrlen == addrlen &&
memcmp(rcv->addr, addr, addrlen) == 0)
return (rcv);
return (NULL);
}
/*
* Create receive address
*/
struct mibrcvaddr *
mib_rcvaddr_create(struct mibif *ifp, const u_char *addr, size_t addrlen)
{
struct mibrcvaddr *rcv;
u_int i;
if (addrlen + OIDLEN_ifRcvAddressEntry + 1 > ASN_MAXOIDLEN)
return (NULL);
if ((rcv = malloc(sizeof(*rcv))) == NULL)
return (NULL);
rcv->ifindex = ifp->index;
rcv->addrlen = addrlen;
memcpy(rcv->addr, addr, addrlen);
rcv->flags = 0;
rcv->index.len = addrlen + 2;
rcv->index.subs[0] = ifp->index;
rcv->index.subs[1] = addrlen;
for (i = 0; i < addrlen; i++)
rcv->index.subs[i + 2] = addr[i];
INSERT_OBJECT_OID(rcv, &mibrcvaddr_list);
return (rcv);
}
/*
* Delete a receive address
*/
void
mib_rcvaddr_delete(struct mibrcvaddr *rcv)
{
TAILQ_REMOVE(&mibrcvaddr_list, rcv, link);
free(rcv);
}
int
op_rcvaddr(struct snmp_context *ctx __unused, struct snmp_value *value,
u_int sub, u_int iidx __unused, enum snmp_op op)
{
struct mibrcvaddr *rcv;
rcv = NULL; /* make compiler happy */
switch (op) {
case SNMP_OP_GETNEXT:
if ((rcv = NEXT_OBJECT_OID(&mibrcvaddr_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NOSUCHNAME);
index_append(&value->var, sub, &rcv->index);
break;
case SNMP_OP_GET:
if ((rcv = FIND_OBJECT_OID(&mibrcvaddr_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NOSUCHNAME);
break;
case SNMP_OP_SET:
if ((rcv = FIND_OBJECT_OID(&mibrcvaddr_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NO_CREATION);
return (SNMP_ERR_NOT_WRITEABLE);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
abort();
}
switch (value->var.subs[sub - 1]) {
case LEAF_ifRcvAddressStatus:
value->v.integer = 1;
break;
case LEAF_ifRcvAddressType:
value->v.integer = (rcv->flags & MIBRCVADDR_VOLATILE) ? 2 : 3;
break;
}
return (SNMP_ERR_NOERROR);
}

View File

@ -0,0 +1,299 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/snmp_mibII/mibII_route.c,v 1.3 2003/01/28 13:44:35 hbb Exp $
*
* Routing table
*/
#include "mibII.h"
#include "mibII_oid.h"
struct sroute {
TAILQ_ENTRY(sroute) link;
struct asn_oid index;
u_int ifindex;
u_int type;
u_int proto;
};
static TAILQ_HEAD(, sroute) sroute_list = TAILQ_HEAD_INITIALIZER(sroute_list);
static u_int32_t route_tick;
static u_int route_total;
static int
fetch_route(void)
{
u_char *rtab, *next;
size_t len;
struct sroute *r;
struct rt_msghdr *rtm;
struct sockaddr *addrs[RTAX_MAX];
struct sockaddr_in *sa, *gw;
struct in_addr mask, nhop;
in_addr_t ha;
struct mibif *ifp;
while ((r = TAILQ_FIRST(&sroute_list)) != NULL) {
TAILQ_REMOVE(&sroute_list, r, link);
free(r);
}
route_total = 0;
if ((rtab = mib_fetch_rtab(AF_INET, NET_RT_DUMP, 0, &len)) == NULL)
return (-1);
next = rtab;
for (next = rtab; next < rtab + len; next += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *)(void *)next;
if (rtm->rtm_type != RTM_GET ||
!(rtm->rtm_flags & RTF_UP))
continue;
mib_extract_addrs(rtm->rtm_addrs, (u_char *)(rtm + 1), addrs);
if (addrs[RTAX_DST] == NULL || addrs[RTAX_GATEWAY] == NULL ||
addrs[RTAX_DST]->sa_family != AF_INET)
continue;
sa = (struct sockaddr_in *)(void *)addrs[RTAX_DST];
if (rtm->rtm_flags & RTF_HOST) {
mask.s_addr = 0xffffffff;
} else {
if (addrs[RTAX_NETMASK] == NULL ||
addrs[RTAX_NETMASK]->sa_len == 0)
mask.s_addr = 0;
else
mask = ((struct sockaddr_in *)(void *)
addrs[RTAX_NETMASK])->sin_addr;
}
if (addrs[RTAX_GATEWAY] == NULL) {
nhop.s_addr = 0;
} else if (rtm->rtm_flags & RTF_LLINFO) {
nhop = sa->sin_addr;
} else {
gw = (struct sockaddr_in *)(void *)addrs[RTAX_GATEWAY];
if (gw->sin_family != AF_INET)
continue;
nhop = gw->sin_addr;
}
if ((ifp = mib_find_if_sys(rtm->rtm_index)) == NULL) {
mib_iflist_bad = 1;
continue;
}
if ((r = malloc(sizeof(*r))) == NULL) {
syslog(LOG_ERR, "%m");
continue;
}
route_total++;
r->index.len = 13;
ha = ntohl(sa->sin_addr.s_addr);
r->index.subs[0] = (ha >> 24) & 0xff;
r->index.subs[1] = (ha >> 16) & 0xff;
r->index.subs[2] = (ha >> 8) & 0xff;
r->index.subs[3] = (ha >> 0) & 0xff;
ha = ntohl(mask.s_addr);
r->index.subs[4] = (ha >> 24) & 0xff;
r->index.subs[5] = (ha >> 16) & 0xff;
r->index.subs[6] = (ha >> 8) & 0xff;
r->index.subs[7] = (ha >> 0) & 0xff;
r->index.subs[8] = 0;
ha = ntohl(nhop.s_addr);
r->index.subs[9] = (ha >> 24) & 0xff;
r->index.subs[10] = (ha >> 16) & 0xff;
r->index.subs[11] = (ha >> 8) & 0xff;
r->index.subs[12] = (ha >> 0) & 0xff;
r->ifindex = ifp->index;
r->type = (rtm->rtm_flags & RTF_LLINFO) ? 3 :
(rtm->rtm_flags & RTF_REJECT) ? 2 : 4;
/* cannot really know, what protocol it runs */
r->proto = (rtm->rtm_flags & RTF_LOCAL) ? 2 :
(rtm->rtm_flags & RTF_STATIC) ? 3 :
(rtm->rtm_flags & RTF_DYNAMIC) ? 4 : 10;
INSERT_OBJECT_OID(r, &sroute_list);
}
free(rtab);
route_tick = get_ticks();
return (0);
}
/*
* Table
*/
int
op_route_table(struct snmp_context *ctx __unused, struct snmp_value *value,
u_int sub, u_int iidx __unused, enum snmp_op op)
{
static struct sroute *r;
if (route_tick < this_tick)
if (fetch_route() == -1)
return (SNMP_ERR_GENERR);
switch (op) {
case SNMP_OP_GETNEXT:
if ((r = NEXT_OBJECT_OID(&sroute_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NOSUCHNAME);
index_append(&value->var, sub, &r->index);
break;
case SNMP_OP_GET:
if ((r = FIND_OBJECT_OID(&sroute_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NOSUCHNAME);
break;
case SNMP_OP_SET:
if ((r = FIND_OBJECT_OID(&sroute_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NO_CREATION);
return (SNMP_ERR_NOT_WRITEABLE);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
abort();
default:
abort();
}
switch (value->var.subs[sub - 1]) {
case LEAF_ipCidrRouteDest:
value->v.ipaddress[0] = r->index.subs[0];
value->v.ipaddress[1] = r->index.subs[1];
value->v.ipaddress[2] = r->index.subs[2];
value->v.ipaddress[3] = r->index.subs[3];
break;
case LEAF_ipCidrRouteMask:
value->v.ipaddress[0] = r->index.subs[4];
value->v.ipaddress[1] = r->index.subs[5];
value->v.ipaddress[2] = r->index.subs[6];
value->v.ipaddress[3] = r->index.subs[7];
break;
case LEAF_ipCidrRouteTos:
value->v.integer = r->index.subs[8];
break;
case LEAF_ipCidrRouteNextHop:
value->v.ipaddress[0] = r->index.subs[9];
value->v.ipaddress[1] = r->index.subs[10];
value->v.ipaddress[2] = r->index.subs[11];
value->v.ipaddress[3] = r->index.subs[12];
break;
case LEAF_ipCidrRouteIfIndex:
value->v.integer = r->ifindex;
break;
case LEAF_ipCidrRouteType:
value->v.integer = r->type;
break;
case LEAF_ipCidrRouteProto:
value->v.integer = r->proto;
break;
case LEAF_ipCidrRouteAge:
value->v.integer = 0;
break;
case LEAF_ipCidrRouteInfo:
value->v.oid = oid_zeroDotZero;
break;
case LEAF_ipCidrRouteNextHopAS:
value->v.integer = 0;
break;
case LEAF_ipCidrRouteMetric1:
case LEAF_ipCidrRouteMetric2:
case LEAF_ipCidrRouteMetric3:
case LEAF_ipCidrRouteMetric4:
case LEAF_ipCidrRouteMetric5:
value->v.integer = -1;
break;
case LEAF_ipCidrRouteStatus:
value->v.integer = 1;
break;
}
return (SNMP_ERR_NOERROR);
}
/*
* scalars
*/
int
op_route(struct snmp_context *ctx __unused, struct snmp_value *value,
u_int sub, u_int iidx __unused, enum snmp_op op)
{
switch (op) {
case SNMP_OP_GETNEXT:
abort();
case SNMP_OP_GET:
break;
case SNMP_OP_SET:
return (SNMP_ERR_NOT_WRITEABLE);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
abort();
}
if (route_tick < this_tick)
if (fetch_route() == -1)
return (SNMP_ERR_GENERR);
switch (value->var.subs[sub - 1]) {
case LEAF_ipCidrRouteNumber:
value->v.uint32 = route_total;
break;
}
return (SNMP_ERR_NOERROR);
}

View File

@ -0,0 +1,361 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/snmp_mibII/mibII_tcp.c,v 1.4 2003/01/28 13:44:35 hbb Exp $
*
* tcp
*/
#include "mibII.h"
#include "mibII_oid.h"
#include <sys/socketvar.h>
#include <netinet/in_pcb.h>
#include <netinet/tcp.h>
#include <netinet/tcp_var.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_fsm.h>
struct tcp_index {
struct asn_oid index;
struct xtcpcb *tp;
};
static u_int32_t tcp_tick;
static struct tcpstat tcpstat;
static struct xinpgen *xinpgen;
static size_t xinpgen_len;
static u_int tcp_count;
static u_int tcp_total;
static u_int oidnum;
static struct tcp_index *tcpoids;
static int
tcp_compare(const void *p1, const void *p2)
{
const struct tcp_index *t1 = p1;
const struct tcp_index *t2 = p2;
return (asn_compare_oid(&t1->index, &t2->index));
}
static int
fetch_tcp(void)
{
size_t len;
struct xinpgen *ptr;
struct xtcpcb *tp;
struct tcp_index *oid;
in_addr_t inaddr;
len = sizeof(tcpstat);
if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, NULL, 0) == -1) {
syslog(LOG_ERR, "net.inet.tcp.stats: %m");
return (-1);
}
if (len != sizeof(tcpstat)) {
syslog(LOG_ERR, "net.inet.tcp.stats: wrong size");
return (-1);
}
len = 0;
if (sysctlbyname("net.inet.tcp.pcblist", NULL, &len, NULL, 0) == -1) {
syslog(LOG_ERR, "net.inet.tcp.pcblist: %m");
return (-1);
}
if (len > xinpgen_len) {
if ((ptr = realloc(xinpgen, len)) == NULL) {
syslog(LOG_ERR, "%zu: %m", len);
return (-1);
}
xinpgen = ptr;
xinpgen_len = len;
}
if (sysctlbyname("net.inet.tcp.pcblist", xinpgen, &len, NULL, 0) == -1) {
syslog(LOG_ERR, "net.inet.tcp.pcblist: %m");
return (-1);
}
tcp_tick = get_ticks();
tcp_count = 0;
tcp_total = 0;
for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len);
ptr->xig_len > sizeof(struct xinpgen);
ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) {
tp = (struct xtcpcb *)ptr;
if (tp->xt_inp.inp_gencnt > xinpgen->xig_gen ||
(tp->xt_inp.inp_vflag & INP_IPV4) == 0)
continue;
tcp_total++;
if (tp->xt_tp.t_state == TCPS_ESTABLISHED ||
tp->xt_tp.t_state == TCPS_CLOSE_WAIT)
tcp_count++;
}
if (oidnum < tcp_total) {
oid = realloc(tcpoids, tcp_total * sizeof(tcpoids[0]));
if (oid == NULL) {
free(tcpoids);
oidnum = 0;
return (0);
}
tcpoids = oid;
oidnum = tcp_total;
}
oid = tcpoids;
for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len);
ptr->xig_len > sizeof(struct xinpgen);
ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) {
tp = (struct xtcpcb *)ptr;
if (tp->xt_inp.inp_gencnt > xinpgen->xig_gen ||
(tp->xt_inp.inp_vflag & INP_IPV4) == 0)
continue;
oid->tp = tp;
oid->index.len = 10;
inaddr = ntohl(tp->xt_inp.inp_laddr.s_addr);
oid->index.subs[0] = (inaddr >> 24) & 0xff;
oid->index.subs[1] = (inaddr >> 16) & 0xff;
oid->index.subs[2] = (inaddr >> 8) & 0xff;
oid->index.subs[3] = (inaddr >> 0) & 0xff;
oid->index.subs[4] = ntohs(tp->xt_inp.inp_lport);
inaddr = ntohl(tp->xt_inp.inp_faddr.s_addr);
oid->index.subs[5] = (inaddr >> 24) & 0xff;
oid->index.subs[6] = (inaddr >> 16) & 0xff;
oid->index.subs[7] = (inaddr >> 8) & 0xff;
oid->index.subs[8] = (inaddr >> 0) & 0xff;
oid->index.subs[9] = ntohs(tp->xt_inp.inp_fport);
oid++;
}
qsort(tcpoids, tcp_total, sizeof(tcpoids[0]), tcp_compare);
return (0);
}
/*
* Scalars
*/
int
op_tcp(struct snmp_context *ctx __unused, struct snmp_value *value,
u_int sub, u_int iidx __unused, enum snmp_op op)
{
switch (op) {
case SNMP_OP_GETNEXT:
abort();
case SNMP_OP_GET:
break;
case SNMP_OP_SET:
return (SNMP_ERR_NOT_WRITEABLE);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
abort();
}
if (tcp_tick < this_tick)
if (fetch_tcp() == -1)
return (SNMP_ERR_GENERR);
switch (value->var.subs[sub - 1]) {
case LEAF_tcpRtoAlgorithm:
value->v.integer = 4; /* Van Jacobson */
break;
#define hz clockinfo.hz
case LEAF_tcpRtoMin:
value->v.integer = 1000 * TCPTV_MIN / hz;
break;
case LEAF_tcpRtoMax:
value->v.integer = 1000 * TCPTV_REXMTMAX / hz;
break;
#undef hz
case LEAF_tcpMaxConn:
value->v.integer = -1;
break;
case LEAF_tcpActiveOpens:
value->v.uint32 = tcpstat.tcps_connattempt;
break;
case LEAF_tcpPassiveOpens:
value->v.uint32 = tcpstat.tcps_accepts;
break;
case LEAF_tcpAttemptFails:
value->v.uint32 = tcpstat.tcps_conndrops;
break;
case LEAF_tcpEstabResets:
value->v.uint32 = tcpstat.tcps_drops;
break;
case LEAF_tcpCurrEstab:
value->v.uint32 = tcp_count;
break;
case LEAF_tcpInSegs:
value->v.uint32 = tcpstat.tcps_rcvtotal;
break;
case LEAF_tcpOutSegs:
value->v.uint32 = tcpstat.tcps_sndtotal -
tcpstat.tcps_sndrexmitpack;
break;
case LEAF_tcpRetransSegs:
value->v.uint32 = tcpstat.tcps_sndrexmitpack;
break;
case LEAF_tcpInErrs:
value->v.uint32 = tcpstat.tcps_rcvbadsum +
tcpstat.tcps_rcvbadoff +
tcpstat.tcps_rcvshort;
break;
}
return (SNMP_ERR_NOERROR);
}
int
op_tcpconn(struct snmp_context *ctx __unused, struct snmp_value *value,
u_int sub, u_int iidx __unused, enum snmp_op op)
{
u_int i;
if (tcp_tick < this_tick)
if (fetch_tcp() == -1)
return (SNMP_ERR_GENERR);
switch (op) {
case SNMP_OP_GETNEXT:
for (i = 0; i < tcp_total; i++)
if (index_compare(&value->var, sub, &tcpoids[i].index) < 0)
break;
if (i == tcp_total)
return (SNMP_ERR_NOSUCHNAME);
index_append(&value->var, sub, &tcpoids[i].index);
break;
case SNMP_OP_GET:
for (i = 0; i < tcp_total; i++)
if (index_compare(&value->var, sub, &tcpoids[i].index) == 0)
break;
if (i == tcp_total)
return (SNMP_ERR_NOSUCHNAME);
break;
case SNMP_OP_SET:
return (SNMP_ERR_NOT_WRITEABLE);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
default:
abort();
}
switch (value->var.subs[sub - 1]) {
case LEAF_tcpConnState:
switch (tcpoids[i].tp->xt_tp.t_state) {
case TCPS_CLOSED:
value->v.integer = 1;
break;
case TCPS_LISTEN:
value->v.integer = 2;
break;
case TCPS_SYN_SENT:
value->v.integer = 3;
break;
case TCPS_SYN_RECEIVED:
value->v.integer = 4;
break;
case TCPS_ESTABLISHED:
value->v.integer = 5;
break;
case TCPS_CLOSE_WAIT:
value->v.integer = 8;
break;
case TCPS_FIN_WAIT_1:
value->v.integer = 6;
break;
case TCPS_CLOSING:
value->v.integer = 10;
break;
case TCPS_LAST_ACK:
value->v.integer = 9;
break;
case TCPS_FIN_WAIT_2:
value->v.integer = 7;
break;
case TCPS_TIME_WAIT:
value->v.integer = 11;
break;
default:
value->v.integer = 0;
break;
}
break;
case LEAF_tcpConnLocalAddress:
value->v.ipaddress[0] = tcpoids[i].index.subs[0];
value->v.ipaddress[1] = tcpoids[i].index.subs[1];
value->v.ipaddress[2] = tcpoids[i].index.subs[2];
value->v.ipaddress[3] = tcpoids[i].index.subs[3];
break;
case LEAF_tcpConnLocalPort:
value->v.integer = tcpoids[i].index.subs[4];
break;
case LEAF_tcpConnRemAddress:
value->v.ipaddress[0] = tcpoids[i].index.subs[5];
value->v.ipaddress[1] = tcpoids[i].index.subs[6];
value->v.ipaddress[2] = tcpoids[i].index.subs[7];
value->v.ipaddress[3] = tcpoids[i].index.subs[8];
break;
case LEAF_tcpConnRemPort:
value->v.integer = tcpoids[i].index.subs[9];
break;
}
return (SNMP_ERR_NOERROR);
}

View File

@ -0,0 +1,248 @@
#
# Copyright (c) 2001-2003
# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
# All rights reserved.
#
# Author: Harti Brandt <harti@freebsd.org>
#
# Redistribution of this software and documentation 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 or documentation 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.
# 3. Neither the name of the Institute nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
# AND ITS 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
# FRAUNHOFER FOKUS OR ITS 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/snmp_mibII/mibII_tree.def,v 1.10 2002/02/06 12:43:51 hbb Exp $
#
# Definition of the standard interfaces and ip trees.
#
(1 internet
(2 mgmt
(1 mib2
(2 interfaces
(1 ifNumber INTEGER op_interfaces GET)
(2 ifTable
(1 ifEntry : INTEGER op_ifentry
(1 ifIndex INTEGER GET)
(2 ifDescr OCTETSTRING GET)
(3 ifType INTEGER GET)
(4 ifMtu INTEGER32 GET)
(5 ifSpeed GAUGE GET)
(6 ifPhysAddress OCTETSTRING GET)
(7 ifAdminStatus INTEGER GET SET)
(8 ifOperStatus INTEGER GET)
(9 ifLastChange TIMETICKS GET)
(10 ifInOctets COUNTER GET)
(11 ifInUcastPkts COUNTER GET)
(12 ifInNUcastPkts COUNTER GET)
(13 ifInDiscards COUNTER GET)
(14 ifInErrors COUNTER GET)
(15 ifInUnknownProtos COUNTER GET)
(16 ifOutOctets COUNTER GET)
(17 ifOutUcastPkts COUNTER GET)
(18 ifOutNUcastPkts COUNTER GET)
(19 ifOutDiscards COUNTER GET)
(20 ifOutErrors COUNTER GET)
(21 ifOutQLen GAUGE GET)
(22 ifSpecific OID GET)
))
)
(4 ip
(1 ipForwarding INTEGER op_ip GET SET)
(2 ipDefaultTTL INTEGER op_ip GET SET)
(3 ipInReceives COUNTER op_ipstat GET)
(4 ipInHdrErrors COUNTER op_ipstat GET)
(5 ipInAddrErrors COUNTER op_ipstat GET)
(6 ipForwDatagrams COUNTER op_ipstat GET)
(7 ipInUnknownProtos COUNTER op_ipstat GET)
(8 ipInDiscards COUNTER op_ipstat GET)
(9 ipInDelivers COUNTER op_ipstat GET)
(10 ipOutRequests COUNTER op_ipstat GET)
(11 ipOutDiscards COUNTER op_ipstat GET)
(12 ipOutNoRoutes COUNTER op_ipstat GET)
(13 ipReasmTimeout INTEGER32 op_ipstat GET)
(14 ipReasmReqds COUNTER op_ipstat GET)
(15 ipReasmOKs COUNTER op_ipstat GET)
(16 ipReasmFails COUNTER op_ipstat GET)
(17 ipFragOKs COUNTER op_ipstat GET)
(18 ipFragFails COUNTER op_ipstat GET)
(19 ipFragCreates COUNTER op_ipstat GET)
(20 ipAddrTable
(1 ipAddrEntry : IPADDRESS op_ipaddr
(1 ipAdEntAddr IPADDRESS GET)
(2 ipAdEntIfIndex INTEGER GET SET)
(3 ipAdEntNetMask IPADDRESS GET SET)
(4 ipAdEntBcastAddr INTEGER GET SET)
(5 ipAdEntReasmMaxSize INTEGER GET)
))
(22 ipNetToMediaTable
(1 ipNetToMediaEntry : INTEGER IPADDRESS op_nettomedia
(1 ipNetToMediaIfIndex INTEGER GET)
(2 ipNetToMediaPhysAddress OCTETSTRING GET)
(3 ipNetToMediaNetAddress IPADDRESS GET)
(4 ipNetToMediaType INTEGER GET)
))
(23 ipRoutingDiscards INTEGER op_ipstat) # not available
(24 ipForward
(3 ipCidrRouteNumber GAUGE op_route GET)
(4 ipCidrRouteTable
(1 ipCidrRouteEntry : IPADDRESS IPADDRESS INTEGER IPADDRESS op_route_table
(1 ipCidrRouteDest IPADDRESS GET)
(2 ipCidrRouteMask IPADDRESS GET)
(3 ipCidrRouteTos INTEGER GET)
(4 ipCidrRouteNextHop IPADDRESS GET)
(5 ipCidrRouteIfIndex INTEGER GET) # SET
(6 ipCidrRouteType INTEGER GET) # SET
(7 ipCidrRouteProto INTEGER GET)
(8 ipCidrRouteAge INTEGER GET)
(9 ipCidrRouteInfo OID GET) # SET
(10 ipCidrRouteNextHopAS INTEGER GET) # SET
(11 ipCidrRouteMetric1 INTEGER GET) # SET
(12 ipCidrRouteMetric2 INTEGER GET) # SET
(13 ipCidrRouteMetric3 INTEGER GET) # SET
(14 ipCidrRouteMetric4 INTEGER GET) # SET
(15 ipCidrRouteMetric5 INTEGER GET) # SET
(16 ipCidrRouteStatus INTEGER GET) # SET
))
)
)
(5 icmp
(1 icmpInMsgs COUNTER op_icmpstat GET)
(2 icmpInErrors COUNTER op_icmpstat GET)
(3 icmpInDestUnreachs COUNTER op_icmpstat GET)
(4 icmpInTimeExcds COUNTER op_icmpstat GET)
(5 icmpInParmProbs COUNTER op_icmpstat GET)
(6 icmpInSrcQuenchs COUNTER op_icmpstat GET)
(7 icmpInRedirects COUNTER op_icmpstat GET)
(8 icmpInEchos COUNTER op_icmpstat GET)
(9 icmpInEchoReps COUNTER op_icmpstat GET)
(10 icmpInTimestamps COUNTER op_icmpstat GET)
(11 icmpInTimestampReps COUNTER op_icmpstat GET)
(12 icmpInAddrMasks COUNTER op_icmpstat GET)
(13 icmpInAddrMaskReps COUNTER op_icmpstat GET)
(14 icmpOutMsgs COUNTER op_icmpstat GET)
(15 icmpOutErrors COUNTER op_icmpstat GET)
(16 icmpOutDestUnreachs COUNTER op_icmpstat GET)
(17 icmpOutTimeExcds COUNTER op_icmpstat GET)
(18 icmpOutParmProbs COUNTER op_icmpstat GET)
(19 icmpOutSrcQuenchs COUNTER op_icmpstat GET)
(20 icmpOutRedirects COUNTER op_icmpstat GET)
(21 icmpOutEchos COUNTER op_icmpstat GET)
(22 icmpOutEchoReps COUNTER op_icmpstat GET)
(23 icmpOutTimestamps COUNTER op_icmpstat GET)
(24 icmpOutTimestampReps COUNTER op_icmpstat GET)
(25 icmpOutAddrMasks COUNTER op_icmpstat GET)
(26 icmpOutAddrMaskReps COUNTER op_icmpstat GET)
)
(6 tcp
(1 tcpRtoAlgorithm INTEGER op_tcp GET)
(2 tcpRtoMin INTEGER32 op_tcp GET)
(3 tcpRtoMax INTEGER32 op_tcp GET)
(4 tcpMaxConn INTEGER32 op_tcp GET)
(5 tcpActiveOpens COUNTER op_tcp GET)
(6 tcpPassiveOpens COUNTER op_tcp GET)
(7 tcpAttemptFails COUNTER op_tcp GET)
(8 tcpEstabResets COUNTER op_tcp GET)
(9 tcpCurrEstab GAUGE op_tcp GET)
(10 tcpInSegs COUNTER op_tcp GET)
(11 tcpOutSegs COUNTER op_tcp GET)
(12 tcpRetransSegs COUNTER op_tcp GET)
(13 tcpConnTable
(1 tcpConnEntry : IPADDRESS INTEGER IPADDRESS INTEGER op_tcpconn
(1 tcpConnState INTEGER GET)
(2 tcpConnLocalAddress IPADDRESS GET)
(3 tcpConnLocalPort INTEGER GET)
(4 tcpConnRemAddress IPADDRESS GET)
(5 tcpConnRemPort INTEGER GET)
))
(14 tcpInErrs COUNTER op_tcp GET)
(15 tcpOutRsts COUNTER op_tcp) # don't know
)
(7 udp
(1 udpInDatagrams COUNTER op_udp GET)
(2 udpNoPorts COUNTER op_udp GET)
(3 udpInErrors COUNTER op_udp GET)
(4 udpOutDatagrams COUNTER op_udp GET)
(5 udpTable
(1 udpEntry : IPADDRESS INTEGER op_udptable
(1 udpLocalAddress IPADDRESS GET)
(2 udpLocalPort INTEGER GET)
))
)
(31 ifMIB
(1 ifMIBObjects
(1 ifXTable
(1 ifXEntry : INTEGER op_ifxtable
(1 ifName OCTETSTRING GET)
(2 ifInMulticastPkts COUNTER GET)
(3 ifInBroadcastPkts COUNTER GET)
(4 ifOutMulticastPkts COUNTER GET)
(5 ifOutBroadcastPkts COUNTER GET)
(6 ifHCInOctets COUNTER64 GET)
(7 ifHCInUcastPkts COUNTER64 GET)
(8 ifHCInMulticastPkts COUNTER64 GET)
(9 ifHCInBroadcastPkts COUNTER64 GET)
(10 ifHCOutOctets COUNTER64 GET)
(11 ifHCOutUcastPkts COUNTER64 GET)
(12 ifHCOutMulticastPkts COUNTER64 GET)
(13 ifHCOutBroadcastPkts COUNTER64 GET)
(14 ifLinkUpDownTrapEnable INTEGER GET SET)
(15 ifHighSpeed GAUGE GET)
(16 ifPromiscuousMode INTEGER GET SET)
(17 ifConnectorPresent INTEGER GET)
(18 ifAlias OCTETSTRING GET)
(19 ifCounterDiscontinuityTime TIMETICKS GET)
))
(2 ifStackTable
(1 ifStackEntry : INTEGER INTEGER op_ifstack
(1 ifStackHigherLayer INTEGER)
(2 ifStackLowerLayer INTEGER)
(3 ifStackStatus INTEGER GET)
))
(4 ifRcvAddressTable
(1 ifRcvAddressEntry : INTEGER OCTETSTRING op_rcvaddr
(1 ifRcvAddressAddress OCTETSTRING)
(2 ifRcvAddressStatus INTEGER GET)
(3 ifRcvAddressType INTEGER GET)
))
(5 ifTableLastChange TIMETICKS op_ifmib GET)
(6 ifStackLastChange TIMETICKS op_ifmib GET)
)
)
(48 ipMIB
)
(49 tcpMIB
)
(50 udpMIB
)
))
(6 snmpV2
(3 snmpModules
(1 snmpMIB
(1 snmpMIBObjects
(5 snmpTraps
(3 linkDown OID op_snmp_trap)
(4 linkUp OID op_snmp_trap)
)
)
)
))
)

View File

@ -0,0 +1,257 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/snmp_mibII/mibII_udp.c,v 1.4 2003/01/28 13:44:35 hbb Exp $
*
* udp
*/
#include "mibII.h"
#include "mibII_oid.h"
#include <sys/socketvar.h>
#include <netinet/in_pcb.h>
#include <netinet/udp.h>
#include <netinet/ip_var.h>
#include <netinet/udp_var.h>
struct udp_index {
struct asn_oid index;
struct xinpcb *inp;
};
static u_int32_t udp_tick;
static struct udpstat udpstat;
static struct xinpgen *xinpgen;
static size_t xinpgen_len;
static u_int udp_total;
static u_int oidnum;
static struct udp_index *udpoids;
static int
udp_compare(const void *p1, const void *p2)
{
const struct udp_index *t1 = p1;
const struct udp_index *t2 = p2;
return (asn_compare_oid(&t1->index, &t2->index));
}
static int
fetch_udp(void)
{
size_t len;
struct xinpgen *ptr;
struct xinpcb *inp;
struct udp_index *oid;
in_addr_t inaddr;
len = sizeof(udpstat);
if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, NULL, 0) == -1) {
syslog(LOG_ERR, "net.inet.udp.stats: %m");
return (-1);
}
if (len != sizeof(udpstat)) {
syslog(LOG_ERR, "net.inet.udp.stats: wrong size");
return (-1);
}
udp_tick = get_ticks();
len = 0;
if (sysctlbyname("net.inet.udp.pcblist", NULL, &len, NULL, 0) == -1) {
syslog(LOG_ERR, "net.inet.udp.pcblist: %m");
return (-1);
}
if (len > xinpgen_len) {
if ((ptr = realloc(xinpgen, len)) == NULL) {
syslog(LOG_ERR, "%zu: %m", len);
return (-1);
}
xinpgen = ptr;
xinpgen_len = len;
}
if (sysctlbyname("net.inet.udp.pcblist", xinpgen, &len, NULL, 0) == -1) {
syslog(LOG_ERR, "net.inet.udp.pcblist: %m");
return (-1);
}
udp_total = 0;
for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len);
ptr->xig_len > sizeof(struct xinpgen);
ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) {
inp = (struct xinpcb *)ptr;
if (inp->xi_inp.inp_gencnt > xinpgen->xig_gen ||
(inp->xi_inp.inp_vflag & INP_IPV4) == 0)
continue;
udp_total++;
}
if (oidnum < udp_total) {
oid = realloc(udpoids, udp_total * sizeof(udpoids[0]));
if (oid == NULL) {
free(udpoids);
oidnum = 0;
return (0);
}
udpoids = oid;
oidnum = udp_total;
}
oid = udpoids;
for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len);
ptr->xig_len > sizeof(struct xinpgen);
ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) {
inp = (struct xinpcb *)ptr;
if (inp->xi_inp.inp_gencnt > xinpgen->xig_gen ||
(inp->xi_inp.inp_vflag & INP_IPV4) == 0)
continue;
oid->inp = inp;
oid->index.len = 5;
inaddr = ntohl(inp->xi_inp.inp_laddr.s_addr);
oid->index.subs[0] = (inaddr >> 24) & 0xff;
oid->index.subs[1] = (inaddr >> 16) & 0xff;
oid->index.subs[2] = (inaddr >> 8) & 0xff;
oid->index.subs[3] = (inaddr >> 0) & 0xff;
oid->index.subs[4] = ntohs(inp->xi_inp.inp_lport);
oid++;
}
qsort(udpoids, udp_total, sizeof(udpoids[0]), udp_compare);
return (0);
}
int
op_udp(struct snmp_context *ctx __unused, struct snmp_value *value,
u_int sub, u_int iidx __unused, enum snmp_op op)
{
switch (op) {
case SNMP_OP_GETNEXT:
abort();
case SNMP_OP_GET:
break;
case SNMP_OP_SET:
return (SNMP_ERR_NOT_WRITEABLE);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
abort();
}
if (udp_tick < this_tick)
if (fetch_udp() == -1)
return (SNMP_ERR_GENERR);
switch (value->var.subs[sub - 1]) {
case LEAF_udpInDatagrams:
value->v.uint32 = udpstat.udps_ipackets;
break;
case LEAF_udpNoPorts:
value->v.uint32 = udpstat.udps_noport +
udpstat.udps_noportbcast +
udpstat.udps_noportmcast;
break;
case LEAF_udpInErrors:
value->v.uint32 = udpstat.udps_hdrops +
udpstat.udps_badsum +
udpstat.udps_badlen +
udpstat.udps_fullsock;
break;
case LEAF_udpOutDatagrams:
value->v.uint32 = udpstat.udps_opackets;
break;
}
return (SNMP_ERR_NOERROR);
}
int
op_udptable(struct snmp_context *ctx __unused, struct snmp_value *value,
u_int sub, u_int iidx __unused, enum snmp_op op)
{
u_int i;
if (udp_tick < this_tick)
if (fetch_udp() == -1)
return (SNMP_ERR_GENERR);
switch (op) {
case SNMP_OP_GETNEXT:
for (i = 0; i < udp_total; i++)
if (index_compare(&value->var, sub, &udpoids[i].index) < 0)
break;
if (i == udp_total)
return (SNMP_ERR_NOSUCHNAME);
index_append(&value->var, sub, &udpoids[i].index);
break;
case SNMP_OP_GET:
for (i = 0; i < udp_total; i++)
if (index_compare(&value->var, sub, &udpoids[i].index) == 0)
break;
if (i == udp_total)
return (SNMP_ERR_NOSUCHNAME);
break;
case SNMP_OP_SET:
return (SNMP_ERR_NOT_WRITEABLE);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
default:
abort();
}
switch (value->var.subs[sub - 1]) {
case LEAF_udpLocalAddress:
value->v.ipaddress[0] = udpoids[i].index.subs[0];
value->v.ipaddress[1] = udpoids[i].index.subs[1];
value->v.ipaddress[2] = udpoids[i].index.subs[2];
value->v.ipaddress[3] = udpoids[i].index.subs[3];
break;
case LEAF_udpLocalPort:
value->v.integer = udpoids[i].index.subs[4];
break;
}
return (SNMP_ERR_NOERROR);
}

View File

@ -0,0 +1,348 @@
.\"
.\" Copyright (c) 2001-2003
.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
.\" All rights reserved.
.\"
.\" Author: Harti Brandt <harti@freebsd.org>
.\"
.\" Redistribution of this software and documentation 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 or documentation 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.
.\" 3. Neither the name of the Institute nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
.\" AND ITS 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
.\" FRAUNHOFER FOKUS OR ITS 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/snmp_mibII/snmp_mibII.3,v 1.1 2002/08/19 09:30:14 hbb Exp $
.\"
.Dd August 19, 2002
.Dt snmp_mibII 3
.Os
.Sh NAME
.Nm mibif_notify_f ,
.Nm mib_netsock ,
.Nm mib_if_set_dyn ,
.Nm mib_refresh_iflist ,
.Nm mib_find_if ,
.Nm mib_find_if_sys ,
.Nm mib_find_if_name ,
.Nm mib_first_if ,
.Nm mib_next_if ,
.Nm mib_register_newif ,
.Nm mib_unregister_newif ,
.Nm mib_fetch_ifmib ,
.Nm mib_if_admin ,
.Nm mib_find_ifa ,
.Nm mib_first_ififa ,
.Nm mib_next_ififa ,
.Nm mib_ifstack_create ,
.Nm mib_ifstack_delete ,
.Nm mib_find_rcvaddr ,
.Nm mib_rcvaddr_create ,
.Nm mib_rcvaddr_delete ,
.Nm mibif_notify ,
.Nm mibif_unnotify
.Nd "mib-2 module for snmpd.
.Sh LIBRARY
.Pq begemotSnmpdModulePath."mibII" = "/usr/local/lib/snmp_mibII.so"
.Sh SYNOPSIS
.In bsnmp/snmpmod.h
.In bsnmp/snmp_mibII.h
.Ft typedef void
.Fn (*mibif_notify_f) "struct mibif *ifp" "enum mibif_notify event" "void *uarg"
.Vt extern int mib_netsock ;
.Ft void
.Fn mib_if_set_dyn "const char *ifname"
.Ft void
.Fn mib_refresh_iflist "void"
.Ft struct mibif *
.Fn mib_find_if "u_int ifindex"
.Ft struct mibif *
.Fn mib_find_if_sys "u_int sysindex"
.Ft struct mibif *
.Fn mib_find_if_name "const char *ifname"
.Ft struct mibif *
.Fn mib_first_if "void"
.Ft struct mibif *
.Fn mib_next_if "const struct mibif *ifp"
.Ft int
.Fn mib_register_newif "int (*func)(struct mibif *)" "const struct lmodule *mod"
.Ft void
.Fn mib_unregister_newif "const struct lmodule *mod"
.Ft int
.Fn mib_fetch_ifmib "struct mibif *ifp"
.Ft int
.Fn mib_if_admin "struct mibif *ifp" "int up"
.Ft struct mibifa *
.Fn mib_find_ifa "struct in_addr ipa"
.Ft struct mibifa *
.Fn mib_first_ififa "const struct mibif *ifp"
.Ft struct mibifa *
.Fn mib_next_ififa "struct mibifa *ifa"
.Ft int
.Fn mib_ifstack_create "const struct mibif *lower" "const struct mibif *upper"
.Ft void
.Fn mib_ifstack_delete "const struct mibif *lower" "const struct mibif *upper"
.Ft struct mibrcvaddr *
.Fn mib_find_rcvaddr "u_int ifindex" "const u_char *addr" "size_t addrlen"
.Ft struct mibrcvaddr *
.Fn mib_rcvaddr_create "struct mibif *ifp" "const u_char *addr" "size_t addrlen"
.Ft void
.Fn mib_rcvaddr_delete "struct mibrcvaddr *addr"
.Ft void *
.Fn mibif_notify "struct mibif *ifp" "const struct lmodule *mod" "mibif_notify_f func" "void *uarg"
.Ft void
.Fn mibif_unnotify "void *reg"
.Sh DESCRIPTION
The
.Nm snmp_mibII
module implements parts of the internet standard MIB-2. Most of the relevant
MIBs are implemented. Some of the tables are restricted to be read-only
instead of read-write. The exact current implementation can be found in
.Pa /usr/local/include/bsnmp/mibII_tree.def .
The module also exports a number of functions and global variables for use
by other modules, that need to handle network interfaces. This man page describes
these functions.
.Ss DIRECT NETWORK ACCESS
The
.Nm
module opens a socket that is used to execute all network related
.Xr ioctl 2
functions. This socket is globally available under the name
.Va mib_netsock .
.Ss NETWORK INTERFACES
The
.Nm
module handles a list of all currently existing network interfaces. It allows
other modules to handle their own interface lists with special information
by providing a mechanism to register to events that change the interface list
(see below). The basic data structure is the interface structure:
.Bd -literal -offset indent
struct mibif {
TAILQ_ENTRY(mibif) link;
u_int flags;
u_int index; /* logical ifindex */
u_int sysindex;
char name[IFNAMSIZ];
char descr[256];
struct ifmibdata mib;
u_int32_t mibtick;
void *specmib;
size_t specmiblen;
u_char *physaddr;
u_int physaddrlen;
int has_connector;
int trap_enable;
u_int32_t counter_disc;
mibif_notify_f xnotify;
void *xnotify_data;
const struct lmodule *xnotify_mod;
};
.Ed
.Pp
The
.Nm
module tries to implement the semantic if
.Va ifIndex
as described in RFC-2863. This RFC states, that an interface indexes may not
be reused. That means, for example, if
.Pa tun
is a synthetic interface type and the system creates the interface
.Pa tun0 ,
destroys this interfaces and again creates a
.Pa tun 0 ,
then these interfaces must have different interface indexes, because in fact
they are different interfaces. If, on the other hand, there is a hardware
interface
.Pa xl0
and this interface disappears, because its driver is unloaded and appears
again, because the driver is loaded again, the interface index must stay
the same.
.Nm
implements this by differentiating between real and synthetic (dynamic)
interfaces. An interface type can be declared dynamic by calling the function
.Fn mib_if_set_dyn
with the name if the interface type (for example
.Qq tun ).
For real interfaces, the module keeps the mapping between the interface name
and its
.Va ifIndex
in a special list, if the interface is unloaded. For dynamic interfaces
a new
.Va ifIndex
is generated each time the interface comes into existance. This
means, that the interface index as seen by SNMP is not the same index
as used by the system. The SNMP
.Va ifIndex
is held in field
.Va index ,
the system's interface index is
.Va sysindex .
.Pp
A call to
.Nm mib_refresh_iflist
causes the entire interface list to be re-created.
.Pp
The interface list can be traversed with the functions
.Fn mib_first_if
and
.Fn mib_next_if .
Be sure not to change the interface list while traversing the list with
these two calls.
.Pp
There are three functions to find an interface by name or index.
.Fn mib_find_if
finds an interface by searching for an SNMP
.Va ifIndex ,
.Fn mib_find_if_sys
finds an interface by searching for a system interface index and
.Fn mib_find_if_name
finds an interface by looking for an interface name. Each of the
function returns
.Li NULL
if the interface cannot be found.
.Pp
The function
.Fn mib_fetch_ifmib
causes the interface MIB to be refreshed from the kernel.
.Pp
The function
.Fn mib_if_admin
can be used to change the interface administrative state to up
(argument is 1) or down (argument is 0).
.Ss INTERFACE EVENTS
A module can register itself to receive a notification when a new entry is
created in the interface list. This is done by calling
.Fn mib_register_newif .
A module can register only one function, a second call to
.Fn mib_register_newif
causes the registration to be overwritten. The registration can be removed
with a call to
.Fn mib_unregister_newif .
If is unregistered automatically, when the registering module is unloaded.
.Pp
A module can also register to events on a specific interface. This is done
by calling
.Fn mibif_notify .
This causes the given callback
.Fa func
to be called with the interface pointer, a notification code and
the user argument
.Fa uarg
when any of the following events occur:
.Bl -tag -width "XXXXX"
.It Li MIBIF_NOTIFY_DESTROY
The interface is destroyed.
.El
.Pp
This mechanism can be used to implement interface type specific MIB parts
in other modules. The registration can be removed with
.Fn mib_unnotify
which the return value from
.Fa mib_notify .
Any notification registration is removed automatically when the interface
is destroyed or the registering module is unloaded.
.Em Note that only one module can register to any given interface .
.Ss INTERFACE ADDRESSES
The
.Nm
module handles a table of interface IP-addresses. These addresses are held
in a
.Bd -literal -offset indent
struct mibifa {
TAILQ_ENTRY(mibifa) link;
struct in_addr inaddr;
struct in_addr inmask;
struct in_addr inbcast;
struct asn_oid index;
u_int ifindex;
u_int flags;
};
.Ed
.Pp
The (ordered) list of IP-addresses on a given interface can be traversed by
calling
.Fn mib_first_ififa
and
.Fn mib_next_ififa .
The list should not be considered read-only.
.Ss INTERFACE RECEIVE ADDRESSES
The internet MIB-2 contains a table of interface receive addresses. These
addresses are handled in:
.Bd -literal -offset indent
struct mibrcvaddr {
TAILQ_ENTRY(mibrcvaddr) link;
struct asn_oid index;
u_int ifindex;
u_char addr[ASN_MAXOIDLEN];
size_t addrlen;
u_int flags;
};
enum {
MIBRCVADDR_VOLATILE = 0x00000001,
MIBRCVADDR_BCAST = 0x00000002,
MIBRCVADDR_HW = 0x00000004,
};
.Ed
.Pp
Note, that the assignment of
.Li MIBRCVADDR_BCAST
is based on a list of known interface types. The flags should be handled
by modules inplementing interface type specific MIBs.
.Pp
A receive address can be created with
.Fn mib_rcvaddr_create
and deleted with
.Fn mib_rcvaddr_delete .
This needs to be done only for addresses that are not automatically handled
by the system.
.Pp
A receive address can be found with
.Fn mib_find_rcvaddr .
.Ss INTERFACE STACK TABLE
The
.Nm
module maintains also the interface stack table. Because for complex stacks,
there is no system supported generic way of getting this information, interface
type specific modules need to help setting up stack entries. The
.Nm
module handles only the top and bottom entries.
.Pp
A table entry is created with
.Fn mib_ifstack_create
and deleted with
.Fn mib_ifstack_delete .
Both functions need the pointers to the interfaces. Entries are automatically
deleted if any of the interfaces of the entry is destroyed. The functions handle
both the stack table and the reverse stack table.
.Sh FILES
.Bl -tag -width ".It Pa /usr/local/include/bsnmp/mibII_tree.def" -compact
.It Pa /usr/local/include/bsnmp/mibII_tree.def
The description of the MIB tree implemented by
.Nm .
.It Pa /usr/local/share/snmp/mibs
The various internet MIBs.
.Sh SEE ALSO
.Xr snmpmod 3 ,
.Xr gensnmptree 1
.Sh STANDARDS
This implementation conforms to the applicable IETF RFCs.
.Sh AUTHORS
.An Hartmut Brandt Aq brandt@fokus.gmd.de

View File

@ -0,0 +1,167 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/snmp_mibII/snmp_mibII.h,v 1.13 2002/03/21 11:18:51 hbb Exp $
*
* Implementation of the interfaces and IP groups of MIB-II.
*/
#ifndef snmp_mibII_h_
#define snmp_mibII_h_
/* forward declaration */
struct mibif;
enum mibif_notify {
MIBIF_NOTIFY_DESTROY
};
typedef void (*mibif_notify_f)(struct mibif *, enum mibif_notify, void *);
/*
* Interfaces. This structure describes one interface as seen in the MIB.
* Interfaces are indexed by ifindex. This is not the same as the index
* used by the system because of the rules in RFC-2863 section 3.1.5. This
* RFC requires, that an ifindex is not to be re-used for ANOTHER dynamically
* interfaces once the interface was deleted. The system's ifindex is in
* sysindex. Mapping is via the mapping table below.
*/
struct mibif {
TAILQ_ENTRY(mibif) link;
u_int flags;
u_int index; /* the logical ifindex */
u_int sysindex;
char name[IFNAMSIZ];
char descr[256];
struct ifmibdata mib;
u_int32_t mibtick;
void *specmib;
size_t specmiblen;
u_char *physaddr;
u_int physaddrlen;
int has_connector;
int trap_enable;
u_int32_t counter_disc;
/*
* This is needed to handle interface type specific information
* in sub-modules. It contains a function pointer which handles
* notifications and a data pointer to arbitrary data.
* Should be set via the mibif_notify function.
*/
mibif_notify_f xnotify;
void *xnotify_data;
const struct lmodule *xnotify_mod;
};
/*
* Interface IP-address table.
*/
struct mibifa {
TAILQ_ENTRY(mibifa) link;
struct in_addr inaddr;
struct in_addr inmask;
struct in_addr inbcast;
struct asn_oid index; /* index for table search */
u_int ifindex;
u_int flags;
};
/*
* Interface receive addresses. Interface link-level multicast, broadcast
* and hardware addresses are handled automatically.
*/
struct mibrcvaddr {
TAILQ_ENTRY(mibrcvaddr) link;
struct asn_oid index;
u_int ifindex;
u_char addr[ASN_MAXOIDLEN];
size_t addrlen;
u_int flags;
};
enum {
MIBRCVADDR_VOLATILE = 0x00000001,
MIBRCVADDR_BCAST = 0x00000002,
MIBRCVADDR_HW = 0x00000004,
};
/* network socket */
extern int mib_netsock;
/* set an interface name to dynamic mode */
void mib_if_set_dyn(const char *);
/* re-read the systems interface list */
void mib_refresh_iflist(void);
/* find interface by index */
struct mibif *mib_find_if(u_int);
struct mibif *mib_find_if_sys(u_int);
struct mibif *mib_find_if_name(const char *);
/* iterate through all interfaces */
struct mibif *mib_first_if(void);
struct mibif *mib_next_if(const struct mibif *);
/* register for interface creations */
int mib_register_newif(int (*)(struct mibif *), const struct lmodule *);
void mib_unregister_newif(const struct lmodule *);
/* get fresh MIB data */
int mib_fetch_ifmib(struct mibif *);
/* change the ADMIN status of an interface and refresh the MIB */
int mib_if_admin(struct mibif *, int up);
/* find interface address by address */
struct mibifa *mib_find_ifa(struct in_addr);
/* find first/next address for a given interface */
struct mibifa *mib_first_ififa(const struct mibif *);
struct mibifa *mib_next_ififa(struct mibifa *);
/* create/delete stacking entries */
int mib_ifstack_create(const struct mibif *lower, const struct mibif *upper);
void mib_ifstack_delete(const struct mibif *lower, const struct mibif *upper);
/* find receive address */
struct mibrcvaddr *mib_find_rcvaddr(u_int, const u_char *, size_t);
/* create/delete receive addresses */
struct mibrcvaddr *mib_rcvaddr_create(struct mibif *, const u_char *, size_t);
void mib_rcvaddr_delete(struct mibrcvaddr *);
/* register for interface notification */
void *mibif_notify(struct mibif *, const struct lmodule *, mibif_notify_f,
void *);
void mibif_unnotify(void *);
#endif

View File

@ -0,0 +1,2 @@
dir ../snmp_netgraph
dir ../snmp_mibII

View File

@ -0,0 +1,63 @@
--
-- Copyright (c) 2001-2003
-- Fraunhofer Institute for Open Communication Systems (FhG Fokus).
-- All rights reserved.
--
-- Author: Harti Brandt <harti@freebsd.org>
--
-- Redistribution of this software and documentation 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 or documentation 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.
-- 3. Neither the name of the Institute nor the names of its contributors
-- may be used to endorse or promote products derived from this software
-- without specific prior written permission.
--
-- THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
-- AND ITS 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
-- FRAUNHOFER FOKUS OR ITS 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.3 2002/02/06 12:43:51 hbb 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

View File

@ -0,0 +1,482 @@
--
-- Copyright (c) 2001-2003
-- Fraunhofer Institute for Open Communication Systems (FhG Fokus).
-- All rights reserved.
--
-- Author: Harti Brandt <harti@freebsd.org>
--
-- Redistribution of this software and documentation 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 or documentation 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.
-- 3. Neither the name of the Institute nor the names of its contributors
-- may be used to endorse or promote products derived from this software
-- without specific prior written permission.
--
-- THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
-- AND ITS 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
-- FRAUNHOFER FOKUS OR ITS 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-SNMPD.txt,v 1.18 2002/12/11 15:54:07 hbb Exp $
--
-- Begemot Private SNMPd MIB.
--
BEGEMOT-SNMPD-MIB DEFINITIONS ::= BEGIN
IMPORTS
MODULE-IDENTITY, OBJECT-TYPE, OBJECT-IDENTITY, Counter32,
Unsigned32
FROM SNMPv2-SMI
TEXTUAL-CONVENTION, TruthValue, RowStatus
FROM SNMPv2-TC
MODULE-COMPLIANCE, OBJECT-GROUP
FROM SNMPv2-CONF
begemot
FROM BEGEMOT-MIB;
begemotSnmpd MODULE-IDENTITY
LAST-UPDATED "200212040000Z"
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 MIB module for the Begemot SNMP daemon."
::= { begemot 1 }
begemotSnmpdObjects OBJECT IDENTIFIER ::= { begemotSnmpd 1 }
begemotSnmpdDefs OBJECT IDENTIFIER ::= { begemotSnmpd 2 }
-- --------------------------------------------------------------------------
SectionName ::= TEXTUAL-CONVENTION
DISPLAY-HINT "14a"
STATUS current
DESCRIPTION
"Name of a loadable module. Should consist of alphanumeric characers
only, the first character must be a letter."
SYNTAX OCTET STRING (SIZE(1..14))
-- --------------------------------------------------------------------------
--
-- Agent types
--
begemotSnmpdAgent OBJECT IDENTIFIER ::= { begemotSnmpdDefs 1 }
begemotSnmpdAgentFreeBSD OBJECT-IDENTITY
STATUS current
DESCRIPTION
"Identifies the agent as running on FreeBSD."
::= { begemotSnmpdAgent 1 }
-- --------------------------------------------------------------------------
--
-- The Config Group
--
begemotSnmpdConfig OBJECT IDENTIFIER ::= { begemotSnmpdObjects 1 }
begemotSnmpdTransmitBuffer OBJECT-TYPE
SYNTAX INTEGER (484..65535)
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"The size of the receive buffer in bytes. Larger messages
are dropped by SNMPd."
DEFVAL { 2048 }
::= { begemotSnmpdConfig 1 }
begemotSnmpdReceiveBuffer OBJECT-TYPE
SYNTAX INTEGER (484..65535)
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"The size of the transmit buffer in bytes. Larger messages
cannot be sent by the SNMPd."
DEFVAL { 2048 }
::= { begemotSnmpdConfig 2 }
begemotSnmpdCommunityDisable OBJECT-TYPE
SYNTAX TruthValue
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Disables all access to the CommunityTable from SNMP. Once
set it cannot be cleared."
DEFVAL { false }
::= { begemotSnmpdConfig 3 }
begemotSnmpdTrap1Addr OBJECT-TYPE
SYNTAX IpAddress
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"The trap sink for v1 traps."
::= { begemotSnmpdConfig 4 }
--
-- Trap destinations
--
begemotTrapSinkTable OBJECT-TYPE
SYNTAX SEQUENCE OF BegemotTrapSinkEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"A table with destinations for standard traps."
INDEX { begemotTrapSinkAddr, begemotTrapSinkPort }
::= { begemotSnmpdObjects 2 }
begemotTrapSinkEntry OBJECT-TYPE
SYNTAX BegemotTrapSinkEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Entry describes one trap destination."
INDEX { begemotTrapSinkAddr, begemotTrapSinkPort }
::= { begemotTrapSinkTable 1 }
BegemotTrapSinkEntry ::= SEQUENCE {
begemotTrapSinkAddr IpAddress,
begemotTrapSinkPort INTEGER,
begemotTrapSinkStatus RowStatus
}
begemotTrapSinkAddr OBJECT-TYPE
SYNTAX IpAddress
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Destination IP address of the manager station where to send
traps."
::= { begemotTrapSinkEntry 1 }
begemotTrapSinkPort OBJECT-TYPE
SYNTAX INTEGER (1..65535)
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Destination UDP port of the manager station where to send
traps."
::= { begemotTrapSinkEntry 2 }
begemotTrapSinkStatus OBJECT-TYPE
SYNTAX RowStatus
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Used to create/activate/destroy the entry."
::= { begemotTrapSinkEntry 3 }
--
-- SNMP port table
--
begemotSnmpdPortTable OBJECT-TYPE
SYNTAX SEQUENCE OF BegemotSnmpdPortEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"A table with descriptions of UDP ports to listen on
for SNMP messages."
::= { begemotSnmpdObjects 4 }
begemotSnmpdPortEntry OBJECT-TYPE
SYNTAX BegemotSnmpdPortEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"An entry in the table with descriptions of UDP ports to
listen on for SNMP messages."
INDEX { begemotSnmpdPortAddress, begemotSnmpdPortPort }
::= { begemotSnmpdPortTable 1 }
BegemotSnmpdPortEntry ::= SEQUENCE {
begemotSnmpdPortAddress IpAddress,
begemotSnmpdPortPort INTEGER,
begemotSnmpdPortStatus INTEGER
}
begemotSnmpdPortAddress OBJECT-TYPE
SYNTAX IpAddress
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"The IP address to bind to."
::= { begemotSnmpdPortEntry 1 }
begemotSnmpdPortPort OBJECT-TYPE
SYNTAX INTEGER (1..65535)
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"The UDP port to listen on for SNMP messages."
::= { begemotSnmpdPortEntry 2 }
begemotSnmpdPortStatus OBJECT-TYPE
SYNTAX INTEGER { valid(1), invalid(2) }
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Set status to 1 to create entry, set it to 2 to delete it."
::= { begemotSnmpdPortEntry 3 }
---
--- Community table
---
begemotSnmpdCommunityTable OBJECT-TYPE
SYNTAX SEQUENCE OF BegemotSnmpdCommunityEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"A table with the community strings for access control."
::= { begemotSnmpdObjects 5 }
begemotSnmpdCommunityEntry OBJECT-TYPE
SYNTAX BegemotSnmpdCommunityEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"A table with the community strings for access control.
When begemotSnmpdCommDisable is true, this table disappears."
INDEX { begemotSnmpdCommunityModule, begemotSnmpdCommunityIndex }
::= { begemotSnmpdCommunityTable 1 }
BegemotSnmpdCommunityEntry ::= SEQUENCE {
begemotSnmpdCommunityModule SectionName,
begemotSnmpdCommunityIndex Unsigned32,
begemotSnmpdCommunityString OCTET STRING,
begemotSnmpdCommunityDescr OCTET STRING
}
begemotSnmpdCommunityModule OBJECT-TYPE
SYNTAX SectionName
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Index of the module that has registered this community.
For global communities this is the empty string."
::= { begemotSnmpdCommunityEntry 1 }
begemotSnmpdCommunityIndex OBJECT-TYPE
SYNTAX Unsigned32 (1..4294967295)
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"The numerical index of the community (private to the module)."
::= { begemotSnmpdCommunityEntry 2 }
begemotSnmpdCommunityString OBJECT-TYPE
SYNTAX OCTET STRING
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"The string for access to SNMPd."
::= { begemotSnmpdCommunityEntry 3 }
begemotSnmpdCommunityDescr OBJECT-TYPE
SYNTAX OCTET STRING
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"A description what this community is good for."
::= { begemotSnmpdCommunityEntry 4 }
--
-- Module table
--
begemotSnmpdModuleTable OBJECT-TYPE
SYNTAX SEQUENCE OF BegemotSnmpdModuleEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"A table describing all the currently loaded dynamic modules.
Writing to this table loads and unloads modules."
::= { begemotSnmpdObjects 6 }
begemotSnmpdModuleEntry OBJECT-TYPE
SYNTAX BegemotSnmpdModuleEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"A table entry describing a loadable module."
INDEX { begemotSnmpdModuleSection }
::= { begemotSnmpdModuleTable 1 }
BegemotSnmpdModuleEntry ::= SEQUENCE {
begemotSnmpdModuleSection SectionName,
begemotSnmpdModulePath OCTET STRING,
begemotSnmpdModuleComment OCTET STRING
}
begemotSnmpdModuleSection OBJECT-TYPE
SYNTAX SectionName
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"The string used for matching configuration file sections
and indexes the module table."
::= { begemotSnmpdModuleEntry 1 }
begemotSnmpdModulePath OBJECT-TYPE
SYNTAX OCTET STRING
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"The path name of the module. Set to empty string
to unload a module. The path of an existing module
may not be changed."
::= { begemotSnmpdModuleEntry 2 }
begemotSnmpdModuleComment OBJECT-TYPE
SYNTAX OCTET STRING
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"A comment describing this module."
::= { begemotSnmpdModuleEntry 3 }
-- --------------------------------------------------------------------------
--
-- The STATISTICS Group
--
begemotSnmpdStats OBJECT IDENTIFIER ::= { begemotSnmpdObjects 7 }
begemotSnmpdStatsNoRxBufs OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of times a receive buffer could not be allocated
for a packet."
::= { begemotSnmpdStats 1 }
begemotSnmpdStatsNoTxBufs OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of times a transmit buffer could not be allocated
for a packet."
::= { begemotSnmpdStats 2 }
begemotSnmpdStatsInTooLongPkts OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of packets received that were longer than the
receive buffer. These packets are dropped."
::= { begemotSnmpdStats 3 }
begemotSnmpdStatsInBadPduTypes OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of packets received with a bad type field."
::= { begemotSnmpdStats 4 }
--
-- The Debug Group
--
begemotSnmpdDebug OBJECT IDENTIFIER ::= { begemotSnmpdObjects 8 }
begemotSnmpdDebugDumpPdus OBJECT-TYPE
SYNTAX TruthValue
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Dump PDUs to log file if true."
DEFVAL { false }
::= { begemotSnmpdDebug 1 }
begemotSnmpdDebugSnmpTrace OBJECT-TYPE
SYNTAX Unsigned32
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Tracing flags for the SNMP library. These flags have the
following meaning:
0x00000001 trace GET operator
0x00000002 trace GETNEXT operator
0x00000004 trace SET operator
0x00000008 trace dependency processing
0x00000010 trace node finding
Individual values can be or-ed together."
DEFVAL { 0 }
::= { begemotSnmpdDebug 2 }
begemotSnmpdDebugSyslogPri OBJECT-TYPE
SYNTAX INTEGER (0..8)
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Events with this or higher priority should not be logged."
DEFVAL { 7 } -- don't log debug messages
::= { begemotSnmpdDebug 3 }
--
-- Local port table
--
begemotSnmpdLocalPortTable OBJECT-TYPE
SYNTAX SEQUENCE OF BegemotSnmpdLocalPortEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"A table with descriptions of local (unix domain) ports to listen
on for SNMP messages."
::= { begemotSnmpdObjects 9 }
begemotSnmpdLocalPortEntry OBJECT-TYPE
SYNTAX BegemotSnmpdLocalPortEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"An entry in the table with descriptions of local ports to
listen on for SNMP messages."
INDEX { begemotSnmpdLocalPortPath }
::= { begemotSnmpdLocalPortTable 1 }
BegemotSnmpdLocalPortEntry ::= SEQUENCE {
begemotSnmpdLocalPortPath OCTET STRING,
begemotSnmpdLocalPortStatus INTEGER
}
begemotSnmpdLocalPortPath OBJECT-TYPE
SYNTAX OCTET STRING (SIZE(1..104))
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"The path name to create and listen on."
::= { begemotSnmpdLocalPortEntry 1 }
begemotSnmpdLocalPortStatus OBJECT-TYPE
SYNTAX INTEGER { valid(1), invalid(2) }
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Set status to 1 to create entry, set it to 2 to delete it."
::= { begemotSnmpdLocalPortEntry 2 }
END

View File

@ -0,0 +1,61 @@
--
-- Copyright (c) 2001-2003
-- Fraunhofer Institute for Open Communication Systems (FhG Fokus).
-- All rights reserved.
--
-- Author: Harti Brandt <harti@freebsd.org>
--
-- Redistribution of this software and documentation 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 or documentation 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.
-- 3. Neither the name of the Institute nor the names of its contributors
-- may be used to endorse or promote products derived from this software
-- without specific prior written permission.
--
-- THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
-- AND ITS 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
-- FRAUNHOFER FOKUS OR ITS 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.3 2002/02/06 12:43:51 hbb 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

1145
contrib/bsnmp/snmpd/action.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,256 @@
.\"
.\" Copyright (c) 2001-2003
.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
.\" All rights reserved.
.\"
.\" Author: Harti Brandt <harti@freebsd.org>
.\"
.\" Redistribution of this software and documentation 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 or documentation 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.
.\" 3. Neither the name of the Institute nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
.\" AND ITS 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
.\" FRAUNHOFER FOKUS OR ITS 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/snmpd.1,v 1.2 2002/08/15 13:27:47 hbb Exp $
.\"
.Dd August 15, 2002
.Dt SNMPD 1
.Os
.Sh NAME
.Nm snmpd
.Nd "simple and extendable SNMP daemon"
.Sh SYNOPSIS
.Nm
.Op Fl dh
.Op Fl c Ar file
.Op Fl D Ar options
.Op Fl I Ar paths
.Op Fl l Ar prefix
.Op Fl m Ar variable Ns Op = Ns Ar value
.Op Fl p Ar file
.Sh DESCRIPTION
The
.Nm
daemon servers the internet SNMP (Simple Network Managment Protocol).
It is intended to server only the absolute basic MIBs and implement all other
MIBs through loadable modules. In this way the
.Nm
can be used in unexpected ways.
.Pp
The options are as follows:
.Bl -tag -width ".It Fl D Ar options"
.It Fl d
This option is used for debugging
.Nm
and causes it not to daemonize itself.
.It Fl h
This option prints a short usage message.
.It Fl c Ar file
Use
.Ar file
as configuration file instead of the standard one.
.It Fl D Ar options
Debugging options are specified with a
.Fl o
flag followed by a comma separated string of options.
The following options are available.
.Bl -tag -width ".It Cm trace Ns Cm = Ns Cm level"
.It Cm dump
This option causes all sent and received PDUs to be dumped to the terminal.
.It Cm events
This causes the debugging level of the event library (see
.Xr eventlib 3 )
to be set to 10.
.It Cm trace Ns Cm = Ns Cm level
This option causes the snmp library trace flag to be set to the specified
value. The value can be specified in the usual C-syntax for numbers.
.El
.It Fl I Ar paths
This option specifies a colon separated list of directories to search for
configuration include files. The default is
.Pa /etc:/usr/etc/:/usr/local/etc .
These paths are only searched for include specified within <> parantheses.
.It Fl l Ar prefix
The
.Ar prefix
is used as the default basename for the pid and the configuration files.
.It Fl m Ar variable Ns Op = Ns Ar value
Define a configuration variable.
.It Fl p Ar file
Specify an alternate pid file instead of the default one.
.El
.Sh CONFIGURATION
The
.Nm
reads its configuration from either the default or the user specified
configuration file. The configuration file consists of the following types of
lines:
.Bl -bullet -offset indent
.It
variable assignments
.It
section separators
.It
include directives
.It
MIB variable assignments
.El
.Pp
If a line is too long it can be continued on the next line by ending it with
a backslash. Empty lines and lines who's first non-blank character is a
.Dq #
sign are ignored.
.Pp
All MIB variable assignments of the entire configuration (including nested
configuration files) are handled as one transaction, i.e. as if they arrived
in a single SET PDU. Any failure during the initial configuration read causes
.Nm
to exit. A failure during the configuration read caused by a module load
causes the loading of the module to fail.
.Pp
The configuration is red during initialisation of
.Nm ,
when a module is loaded and when
.Nm
receives a SIGHUP.
.Ss VARIABLE ASSIGNMENTS
Variable assignments can take one of two forms:
.Bd -unfilled -offset indent
variable := string
variable ?= string
.Ed
.Pp
The string reaches from the first non-blank character after the
equal sign until the first new line or
.Dq #
character. In the first case
the string is assigned to the variable unconditionally, in the second case the
variable is only assigned if it does not exist yet.
.Pp
Variable names must begin with a letter or underscore and contain only letters,
digits or underscores.
.Ss SECTION SEPARATORS
The configuration consists of named sections. The MIB variable assignments in
the section named
.Dq snmpd
are executed only during initial setup or when
.Nm
receives a SIGHUP. All other sections are executed when either a module
with the same name as the section is loaded or
.Nm
receives a SIGHUP and that module is already loaded. The default section
at the start of the configuration is
.Dq snmpd .
One can switch to another section with the syntax
.Bd -unfilled -offset indent
%secname
.Ed
.Pp
Where
.Ar secname
is the name of the section. The same
.Ar secname
can be used in more than one place in the configuration. All of these parts are
collected into one section.
.Ss INCLUDE DIRECTIVES
Another configuration file can be included into the current one with the
include directive that takes one of two forms:
.Bd -unfilled -offset indent
\&.include "file"
\&.include <"file">
.Ed
.Pp
The first form causes the file to be searched in the current directory, the
second form causes the file to be searched in the directories specified in
the system include path. Nesting depths is only restricted by available
memory.
.Ss MIB VARIABLE ASSIGNMENTS
A MIB variable is assigned with the syntax
.Bd -unfilled -offset indent
oid [ suboids ] = value
.Ed
.Pp
.Va oid
is the name of the variable to be set. Only the last component of the entire
name is used here. If the variable is a scalar, the index (.0) is automatically
appended and need not to be specified. If the variable is a table column,
the index (
.Va suboids )
must be specified. The index consist of elements each seperated from the
previous one by a dot. Elements may be either numbers, strings or hostnames
enclosed in [] brackets. If the element is a number it is appended
to the current oid. If the element is a string, its length and the
.Tn ASCII
code of each of its characters are appended to the current oid. If the
element is a hostname, the IP address of the host is looked up and the four
elements of the IP address are appended to the oid.
.Pp
For example a oid of
.Bd -unfilled -offset indent
myvariable.27.foooll.[localhost]."&^!"
.Ed
.Pp
results in the oid
.Bd -unfilled -offset indent
myvariable.27.6.102.111.111.111.108.108.127.0.0.1.38.94.33
.Ed
.Pp
The value of the assignment may be either empty, a string or a number.
If a string starts with a letter or an underscore and consists only of
letters, digits, underscores and minus signs, it can be written without
quotes. In all other cases the string must be enclosed in double quotes.
.Sh SUBSTITUTIONS
A variable substitution is written as
.Bd -unfilled -offset indent
$(variable)
.Ed
.Pp
where
.Ar variable
is the name of the variable to substitute. Using an undefined variable is
considered an error.
.Sh FILES
.Bl -tag -width ".It Pa /var/run/ Ns Ao Ar prefix Ac Ns \&.pid" -compact
.It Pa /etc/ Ns Ao Ar prefix Ac Ns \&.config
Default configuration file, where the default
.Aq prefix
is
.Dq snmpd .
.It Pa /var/run/ Ns Ao Ar prefix Ac Ns \&.pid
Default pid file.
.It Pa /etc:/usr/etc/:/usr/local/etc
This is the default search path for system include files.
.It Pa /usr/local/share/snmp/mibs/FOKUS-MIB.txt
.It Pa /usr/local/share/snmp/mibs/BEGEMOT-MIB.txt
.It Pa /usr/local/share/snmp/mibs/BEGEMOT-SNMPD.txt
The definitions for the MIBs implemented in the daemon.
.El
.Sh SEE ALSO
.Xr gensnmptree 1
.Sh STANDARDS
The
.Nm
conforms to the applicable IETF RFCs.
.Sh AUTHORS
.An Hartmut Brandt Aq brandt@fokus.gmd.de
.Sh BUGS
Sure.

1361
contrib/bsnmp/snmpd/config.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,378 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/export.c,v 1.5 2003/01/28 13:44:35 hbb Exp $
*
* Support functions for modules.
*/
#include <sys/types.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <stdarg.h>
#include "snmpmod.h"
#include "snmpd.h"
#include "tree.h"
/*
* Support functions
*/
/*
* This is user for SET of string variables. If 'req' is not -1 then
* the arguments is checked to be of that length. The old value is saved
* in scratch->ptr1 and the new value is allocated and copied.
* If there is an old values it must have been allocated by malloc.
*/
int
string_save(struct snmp_value *value, struct snmp_context *ctx,
ssize_t req_size, u_char **valp)
{
if (req_size != -1 && value->v.octetstring.len != (u_long)req_size)
return (SNMP_ERR_BADVALUE);
ctx->scratch->ptr1 = *valp;
if ((*valp = malloc(value->v.octetstring.len + 1)) == NULL) {
*valp = ctx->scratch->ptr1;
return (SNMP_ERR_RES_UNAVAIL);
}
memcpy(*valp, value->v.octetstring.octets, value->v.octetstring.len);
(*valp)[value->v.octetstring.len] = '\0';
return (0);
}
/*
* Commit a string. This is easy - free the old value.
*/
void
string_commit(struct snmp_context *ctx)
{
free(ctx->scratch->ptr1);
}
/*
* Rollback a string - free new value and copy back old one.
*/
void
string_rollback(struct snmp_context *ctx, u_char **valp)
{
free(*valp);
*valp = ctx->scratch->ptr1;
}
/*
* ROLLBACK or COMMIT fails because instance has disappeared. Free string.
*/
void
string_free(struct snmp_context *ctx)
{
free(ctx->scratch->ptr1);
}
/*
* Get a string value for a response packet
*/
int
string_get(struct snmp_value *value, const u_char *ptr, ssize_t len)
{
if (ptr == NULL) {
value->v.octetstring.len = 0;
value->v.octetstring.octets = NULL;
return (SNMP_ERR_NOERROR);
}
if (len == -1)
len = strlen(ptr);
value->v.octetstring.len = (u_long)len;
if ((value->v.octetstring.octets = malloc((size_t)len)) == NULL)
return (SNMP_ERR_RES_UNAVAIL);
memcpy(value->v.octetstring.octets, ptr, (size_t)len);
return (SNMP_ERR_NOERROR);
}
/*
* Support for IPADDRESS
*
* Save the old IP address in scratch->int1 and set the new one.
*/
int
ip_save(struct snmp_value *value, struct snmp_context *ctx, u_char *valp)
{
ctx->scratch->int1 = (valp[0] << 24) | (valp[1] << 16) | (valp[2] << 8)
| valp[3];
valp[0] = value->v.ipaddress[0];
valp[1] = value->v.ipaddress[1];
valp[2] = value->v.ipaddress[2];
valp[3] = value->v.ipaddress[3];
return (0);
}
/*
* Rollback the address by copying back the old one
*/
void
ip_rollback(struct snmp_context *ctx, u_char *valp)
{
valp[0] = ctx->scratch->int1 >> 24;
valp[1] = ctx->scratch->int1 >> 16;
valp[2] = ctx->scratch->int1 >> 8;
valp[3] = ctx->scratch->int1;
}
/*
* Nothing to do for commit
*/
void
ip_commit(struct snmp_context *ctx __unused)
{
}
/*
* Retrieve an IP address
*/
int
ip_get(struct snmp_value *value, u_char *valp)
{
value->v.ipaddress[0] = valp[0];
value->v.ipaddress[1] = valp[1];
value->v.ipaddress[2] = valp[2];
value->v.ipaddress[3] = valp[3];
return (SNMP_ERR_NOERROR);
}
/*
* Object ID support
*
* Save the old value in a fresh allocated oid pointed to by scratch->ptr1.
*/
int
oid_save(struct snmp_value *value, struct snmp_context *ctx,
struct asn_oid *oid)
{
if ((ctx->scratch->ptr1 = malloc(sizeof(struct asn_oid))) == NULL)
return (SNMP_ERR_RES_UNAVAIL);
*(struct asn_oid *)ctx->scratch->ptr1 = *oid;
*oid = value->v.oid;
return (0);
}
void
oid_rollback(struct snmp_context *ctx, struct asn_oid *oid)
{
*oid = *(struct asn_oid *)ctx->scratch->ptr1;
free(ctx->scratch->ptr1);
}
void
oid_commit(struct snmp_context *ctx)
{
free(ctx->scratch->ptr1);
}
int
oid_get(struct snmp_value *value, const struct asn_oid *oid)
{
value->v.oid = *oid;
return (SNMP_ERR_NOERROR);
}
/*
* Decode an index
*/
int
index_decode(const struct asn_oid *oid, u_int sub, u_int code, ...)
{
va_list ap;
u_int index_count;
void *octs[10];
u_int nocts;
u_int idx;
va_start(ap, code);
index_count = SNMP_INDEX_COUNT(code);
nocts = 0;
for (idx = 0; idx < index_count; idx++) {
switch (SNMP_INDEX(code, idx)) {
case SNMP_SYNTAX_NULL:
break;
case SNMP_SYNTAX_INTEGER:
if (sub == oid->len)
goto err;
*va_arg(ap, int32_t *) = oid->subs[sub++];
break;
case SNMP_SYNTAX_COUNTER64:
if (sub == oid->len)
goto err;
*va_arg(ap, u_int64_t *) = oid->subs[sub++];
break;
case SNMP_SYNTAX_OCTETSTRING:
{
u_char **cval;
size_t *sval;
u_int i;
/* only variable size supported */
if (sub == oid->len)
goto err;
cval = va_arg(ap, u_char **);
sval = va_arg(ap, size_t *);
*sval = oid->subs[sub++];
if (sub + *sval > oid->len)
goto err;
if ((*cval = malloc(*sval)) == NULL) {
syslog(LOG_ERR, "%s: %m", __func__);
goto err;
}
octs[nocts++] = *cval;
for (i = 0; i < *sval; i++) {
if (oid->subs[sub] > 0xff)
goto err;
(*cval)[i] = oid->subs[sub++];
}
break;
}
case SNMP_SYNTAX_OID:
{
struct asn_oid *aval;
u_int i;
if (sub == oid->len)
goto err;
aval = va_arg(ap, struct asn_oid *);
aval->len = oid->subs[sub++];
if (aval->len > ASN_MAXOIDLEN)
goto err;
for (i = 0; i < aval->len; i++)
aval->subs[i] = oid->subs[sub++];
break;
}
case SNMP_SYNTAX_IPADDRESS:
{
u_int8_t *pval;
u_int i;
if (sub + 4 > oid->len)
goto err;
pval = va_arg(ap, u_int8_t *);
for (i = 0; i < 4; i++) {
if (oid->subs[sub] > 0xff)
goto err;
pval[i] = oid->subs[sub++];
}
break;
}
case SNMP_SYNTAX_COUNTER:
case SNMP_SYNTAX_GAUGE:
case SNMP_SYNTAX_TIMETICKS:
if (sub == oid->len)
goto err;
if (oid->subs[sub] > 0xffffffff)
goto err;
*va_arg(ap, u_int32_t *) = oid->subs[sub++];
break;
}
}
va_end(ap);
return (0);
err:
va_end(ap);
while(nocts > 0)
free(octs[--nocts]);
return (-1);
}
/*
* Compare the index part of an OID and an index.
*/
int
index_compare_off(const struct asn_oid *oid, u_int sub,
const struct asn_oid *idx, u_int off)
{
u_int i;
for (i = off; i < idx->len && i < oid->len - sub; i++) {
if (oid->subs[sub + i] < idx->subs[i])
return (-1);
if (oid->subs[sub + i] > idx->subs[i])
return (+1);
}
if (oid->len - sub < idx->len)
return (-1);
if (oid->len - sub > idx->len)
return (+1);
return (0);
}
int
index_compare(const struct asn_oid *oid, u_int sub, const struct asn_oid *idx)
{
return (index_compare_off(oid, sub, idx, 0));
}
/*
* Append an index to an oid
*/
void
index_append_off(struct asn_oid *var, u_int sub, const struct asn_oid *idx,
u_int off)
{
u_int i;
var->len = sub + idx->len;
for (i = off; i < idx->len; i++)
var->subs[sub + i] = idx->subs[i];
}
void
index_append(struct asn_oid *var, u_int sub, const struct asn_oid *idx)
{
index_append_off(var, sub, idx, 0);
}

2038
contrib/bsnmp/snmpd/main.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
#
# Copyright (c) 2001-2003
# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
# All rights reserved.
#
# Author: Harti Brandt <harti@freebsd.org>
#
# Redistribution of this software and documentation 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 or documentation 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.
# 3. Neither the name of the Institute nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
# AND ITS 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
# FRAUNHOFER FOKUS OR ITS 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/snmpd.config,v 1.11 2002/12/11 15:54:08 hbb Exp $
#
# Example configuration file.
#
#
# Set some common variables
#
host := foo.bar.com
location := "Room 200"
contact := "sysmeister@bar.com"
system := 1 # FreeBSD
traphost := noc.bar.com
trapport := 162
read := "public"
write := "geheim"
trap := "mytrap"
#
# Configuration
#
%snmpd
begemotSnmpdDebugDumpPdus = 2
begemotSnmpdDebugSyslogPri = 7
begemotSnmpdCommunityString.0.1 = $(read)
begemotSnmpdCommunityString.0.2 = $(write)
begemotSnmpdCommunityDisable = 1
# open standard SNMP ports
begemotSnmpdPortStatus.[$(host)].161 = 1
begemotSnmpdPortStatus.127.0.0.1.161 = 1
# open a unix domain socket
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
# send traps to the traphost
begemotTrapSinkStatus[$(traphost)].$(trapport) = 4
begemotTrapSinkVersion[$(traphost)].$(trapport) = 2
begemotTrapSinkComm[$(traphost)].$(trapport) = $(trap)
sysContact = $(contact)
sysLocation = $(location)
sysObjectId = 1.3.6.1.4.1.12325.1.1.2.1.$(system)
snmpEnableAuthenTraps = 2
#
# Load MIB-2 module
#
begemotSnmpdModulePath."mibII" = "/usr/local/lib/snmp_mibII.so"
#
# Netgraph module
#
begemotSnmpdModulePath."netgraph" = "/usr/local/lib/snmp_netgraph.so"
%netgraph
begemotNgControlNodeName = "snmpd"

277
contrib/bsnmp/snmpd/snmpd.h Normal file
View File

@ -0,0 +1,277 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/snmpd.h,v 1.17 2003/01/28 13:44:35 hbb Exp $
*
* Private SNMPd data and functions.
*/
#include <sys/queue.h>
#include <isc/eventlib.h>
#define PATH_SYSCONFIG "/etc:/usr/etc:/usr/local/etc"
/*************************************************************
*
* Communities
*/
struct community {
struct lmodule *owner; /* who created the community */
u_int private;/* private name for the module */
u_int value; /* value of this community */
u_char * string; /* the community string */
const u_char * descr; /* description */
TAILQ_ENTRY(community) link;
struct asn_oid index;
};
/* list of all known communities */
extern TAILQ_HEAD(community_list, community) community_list;
/*************************************************************
*
* Request IDs.
*/
struct idrange {
u_int type; /* type id */
int32_t base; /* base of this range */
int32_t size; /* size of this range */
int32_t next; /* generator */
struct lmodule *owner; /* owner module */
TAILQ_ENTRY(idrange) link;
};
/* list of all known ranges */
extern TAILQ_HEAD(idrange_list, idrange) idrange_list;
/* identifier generator */
extern u_int next_idrange;
/* request id generator for traps */
extern u_int trap_reqid;
/*************************************************************
*
* Timers
*/
struct timer {
void (*func)(void *);/* user function */
void *udata; /* user data */
evTimerID id; /* timer id */
struct lmodule *owner; /* owner of the timer */
LIST_ENTRY(timer) link;
};
/* list of all current timers */
extern LIST_HEAD(timer_list, timer) timer_list;
/*************************************************************
*
* File descriptors
*/
struct fdesc {
int fd; /* the file descriptor */
void (*func)(int, void *);/* user function */
void *udata; /* user data */
evFileID id; /* file id */
struct lmodule *owner; /* owner module of the file */
LIST_ENTRY(fdesc) link;
};
/* list of all current selected files */
extern LIST_HEAD(fdesc_list, fdesc) fdesc_list;
/*************************************************************
*
* Loadable modules
*/
# define LM_SECTION_MAX 14
struct lmodule {
char section[LM_SECTION_MAX + 1]; /* and index */
char *path;
u_int flags;
void *handle;
const struct snmp_module *config;
TAILQ_ENTRY(lmodule) link;
TAILQ_ENTRY(lmodule) start;
struct asn_oid index;
};
#define LM_STARTED 0x0001
#define LM_ONSTARTLIST 0x0002
extern TAILQ_HEAD(lmodules, lmodule) lmodules;
struct lmodule *lm_load(const char *, const char *);
void lm_unload(struct lmodule *);
void lm_start(struct lmodule *);
/*************************************************************
*
* SNMP ports
*/
struct snmp_port {
u_int8_t addr[4];/* host byteorder */
u_int16_t port; /* host byteorder */
int sock; /* the socket */
void * id; /* evSelect handle */
struct sockaddr_in ret; /* the return address */
socklen_t retlen; /* length of that address */
TAILQ_ENTRY(snmp_port) link;
struct asn_oid index;
};
TAILQ_HEAD(snmp_port_list, snmp_port);
extern struct snmp_port_list snmp_port_list;
void close_snmp_port(struct snmp_port *);
int open_snmp_port(u_int8_t *, u_int32_t, struct snmp_port **);
struct local_port {
char *name; /* unix path name */
int sock; /* the socket */
void *id; /* evSelect handle */
struct sockaddr_un ret; /* the return address */
socklen_t retlen; /* length of that address */
TAILQ_ENTRY(local_port) link;
struct asn_oid index;
};
TAILQ_HEAD(local_port_list, local_port);
extern struct local_port_list local_port_list;
void close_local_port(struct local_port *);
int open_local_port(u_char *, size_t, struct local_port **);
/*************************************************************
*
* SNMPd scalar configuration.
*/
struct snmpd {
/* transmit buffer size */
u_int32_t txbuf;
/* receive buffer size */
u_int32_t rxbuf;
/* disable community table */
int comm_dis;
/* authentication traps */
int auth_traps;
/* source address for V1 traps */
u_char trap1addr[4];
};
extern struct snmpd snmpd;
/*
* The debug group
*/
struct debug {
u_int dump_pdus;
u_int logpri;
u_int evdebug;
};
extern struct debug debug;
/*
* SNMPd statistics table
*/
struct snmpd_stats {
u_int32_t inPkts; /* total packets received */
u_int32_t inBadVersions; /* unknown version number */
u_int32_t inASNParseErrs; /* fatal parse errors */
u_int32_t inBadCommunityNames;
u_int32_t inBadCommunityUses;
u_int32_t proxyDrops; /* dropped by proxy function */
u_int32_t silentDrops;
u_int32_t inBadPduTypes;
u_int32_t inTooLong;
u_int32_t noTxbuf;
u_int32_t noRxbuf;
};
extern struct snmpd_stats snmpd_stats;
/*
* OR Table
*/
struct objres {
TAILQ_ENTRY(objres) link;
u_int index;
struct asn_oid oid; /* the resource OID */
char descr[256];
u_int32_t uptime;
struct lmodule *module;
};
TAILQ_HEAD(objres_list, objres);
extern struct objres_list objres_list;
/*
* Trap Sink Table
*/
struct trapsink {
TAILQ_ENTRY(trapsink) link;
struct asn_oid index;
u_int status;
int socket;
u_char comm[SNMP_COMMUNITY_MAXLEN];
int version;
};
enum {
TRAPSINK_ACTIVE = 1,
TRAPSINK_NOT_IN_SERVICE = 2,
TRAPSINK_NOT_READY = 3,
TRAPSINK_DESTROY = 6,
TRAPSINK_V1 = 1,
TRAPSINK_V2 = 2,
};
TAILQ_HEAD(trapsink_list, trapsink);
extern struct trapsink_list trapsink_list;
extern const char *syspath;
/* snmpSerialNo */
extern int32_t snmp_serial_no;
int init_actvals(void);
int read_config(const char *, struct lmodule *);
int define_macro(const char *name, const char *value);

89
contrib/bsnmp/snmpd/snmpd.sh Executable file
View File

@ -0,0 +1,89 @@
#!/bin/sh
#
# Copyright (c) 2001-2003
# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
# All rights reserved.
#
# Author: Harti Brandt <harti@freebsd.org>
#
# Redistribution of this software and documentation 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 or documentation 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.
# 3. Neither the name of the Institute nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
# AND ITS 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
# FRAUNHOFER FOKUS OR ITS 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/snmpd.sh,v 1.1 2002/12/04 11:15:23 hbb Exp $
#
# SNMPd startup script
#
SNMPD=/usr/local/bin/bsnmpd
PID=/var/run/snmpd.pid
CONF=/etc/snmpd.conf
case "$1" in
start)
if [ -r ${PID} ] ; then
if kill -0 `cat ${PID}` ; then
echo "snmpd already running -- pid `cat ${PID}`" >/dev/stderr
exit 1
fi
rm -f ${PID}
fi
if ${SNMPD} -c ${CONF} -p ${PID} ; then
echo "snmpd started"
fi
;;
stop)
if [ -r ${PID} ] ; then
if kill -0 `cat ${PID}` ; then
if kill -15 `cat ${PID}` ; then
echo "snmpd stopped"
exit 0
fi
echo "cannot kill snmpd" >/dev/stderr
exit 1
fi
echo "stale pid file -- removing" >/dev/stderr
rm -f ${PID}
exit 1
fi
echo "snmpd not running" >/dev/stderr
;;
status)
if [ ! -r ${PID} ] ; then
echo "snmpd not running"
elif kill -0 `cat ${PID}` ; then
echo "snmpd pid `cat ${PID}`"
else
echo "stale pid file -- pid `cat ${PID}`"
fi
;;
*)
echo "usage: `basename $0` {start|stop|status}"
exit 1
esac
exit 0

View File

@ -0,0 +1,861 @@
.\"
.\" Copyright (c) 2001-2003
.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
.\" All rights reserved.
.\"
.\" Author: Harti Brandt <harti@freebsd.org>
.\"
.\" Redistribution of this software and documentation 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 or documentation 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.
.\" 3. Neither the name of the Institute nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
.\" AND ITS 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
.\" FRAUNHOFER FOKUS OR ITS 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/snmpmod.3,v 1.3 2003/01/28 13:44:35 hbb Exp $
.\"
.Dd August 16, 2002
.Dt snmpmod 3
.Os
.Sh NAME
.Nm INSERT_OBJECT_OID_LINK_INDEX ,
.Nm INSERT_OBJECT_INT_LINK_INDEX ,
.Nm FIND_OBJECT_OID_LINK_INDEX ,
.Nm NEXT_OBJECT_OID_LINK_INDEX ,
.Nm FIND_OBJECT_INT_LINK_INDEX ,
.Nm NEXT_OBJECT_INT_LINK_INDEX ,
.Nm INSERT_OBJECT_OID_LINK ,
.Nm INSERT_OBJECT_INT_LINK ,
.Nm FIND_OBJECT_OID_LINK ,
.Nm NEXT_OBJECT_OID_LINK ,
.Nm FIND_OBJECT_INT_LINK ,
.Nm NEXT_OBJECT_INT_LINK ,
.Nm INSERT_OBJECT_OID ,
.Nm INSERT_OBJECT_INT ,
.Nm FIND_OBJECT_OID ,
.Nm FIND_OBJECT_INT ,
.Nm NEXT_OBJECT_OID ,
.Nm NEXT_OBJECT_INT ,
.Nm this_tick ,
.Nm start_tick ,
.Nm get_ticks ,
.Nm systemg ,
.Nm comm_define ,
.Nm community ,
.Nm oid_zeroDotZero ,
.Nm reqid_allocate ,
.Nm reqid_next ,
.Nm reqid_base ,
.Nm reqid_istype ,
.Nm reqid_type ,
.Nm timer_start ,
.Nm timer_stop ,
.Nm fd_select ,
.Nm fd_deselect ,
.Nm fd_suspend ,
.Nm fd_resume ,
.Nm or_register ,
.Nm or_unregister ,
.Nm buf_alloc ,
.Nm buf_size ,
.Nm snmp_input_start ,
.Nm snmp_input_finish ,
.Nm snmp_output ,
.Nm snmp_send_port ,
.Nm snmp_send_trap ,
.Nm string_save ,
.Nm string_commit ,
.Nm string_rollback ,
.Nm string_get ,
.Nm string_free ,
.Nm ip_save ,
.Nm ip_rollback ,
.Nm ip_commit ,
.Nm ip_get ,
.Nm oid_save ,
.Nm oid_rollback ,
.Nm oid_commit ,
.Nm oid_get ,
.Nm index_decode ,
.Nm index_compare ,
.Nm index_compare_off ,
.Nm index_append ,
.Nm index_append_off
.Nd "SNMP daemon loadable module interface"
.Sh LIBRARY
Begemot SNMP library
.Pq libbsnmp, -lbsnmp
.Sh SYNOPSIS
.In bsnmp/snmpmod.h
.Fn INSERT_OBJECT_OID_LINK_INDEX "PTR" "LIST" "LINK" "INDEX"
.Fn INSERT_OBJECT_INT_LINK_INDEX "PTR" "LIST" "LINK" "INDEX"
.Fn FIND_OBJECT_OID_LINK_INDEX "LIST" "OID" "SUB" "LINK" "INDEX"
.Fn FIND_OBJECT_INT_LINK_INDEX "LIST" "OID" "SUB" "LINK" "INDEX"
.Fn NEXT_OBJECT_OID_LINK_INDEX "LIST" "OID" "SUB" "LINK" "INDEX"
.Fn NEXT_OBJECT_INT_LINK_INDEX "LIST" "OID" "SUB" "LINK" "INDEX"
.Fn INSERT_OBJECT_OID_LINK "PTR" "LIST" "LINK"
.Fn INSERT_OBJECT_INT_LINK "PTR" "LIST" "LINK"
.Fn FIND_OBJECT_OID_LINK "LIST" "OID" "SUB" "LINK"
.Fn FIND_OBJECT_INT_LINK "LIST" "OID" "SUB" "LINK"
.Fn NEXT_OBJECT_OID_LINK "LIST" "OID" "SUB" "LINK"
.Fn NEXT_OBJECT_INT_LINK "LIST" "OID" "SUB" "LINK"
.Fn INSERT_OBJECT_OID "PTR" "LIST"
.Fn INSERT_OBJECT_INT "PTR" "LIST"
.Fn FIND_OBJECT_OID "LIST" "OID" "SUB"
.Fn FIND_OBJECT_INT "LIST" "OID" "SUB"
.Fn NEXT_OBJECT_OID "LIST" "OID" "SUB"
.Fn NEXT_OBJECT_INT "LIST" "OID" "SUB"
.Vt extern u_int32_t this_tick ;
.Vt extern u_int32_t start_tick ;
.Ft u_int32_t
.Fn get_ticks "void"
.Vt extern struct systemg systemg ;
.Ft u_int
.Fn comm_define "u_int priv" "const char *descr" "struct lmodule *mod" "const char *str"
.Ft const char *
.Fn comm_string "u_int comm"
.Vt extern u_int community ;
.Vt extern const struct asn_oid oid_zeroDotZero ;
.Ft u_int
.Fn reqid_allocate "int size" "struct lmodule *mod"
.Ft int32_t
.Fn reqid_next "u_int type"
.Ft int32_t
.Fn reqid_base "u_int type"
.Ft int
.Fn reqid_istype "int32_t reqid" "u_int type"
.Ft u_int
.Fn reqid_type "int32_t reqid"
.Ft void *
.Fn timer_start "u_int ticks" "void (*func)(void *)" "void *uarg" "struct lmodule *mod"
.Ft void
.Fn timer_stop "void *timer_id"
.Ft void *
.Fn fd_select "int fd" "void (*func)(int, void *)" "void *uarg" "struct lmodule *mod"
.Ft void
.Fn fd_deselect "void *fd_id"
.Ft void
.Fn fd_suspend "void *fd_id"
.Ft int
.Fn fd_resume "void *fd_id"
.Ft u_int
.Fn or_register "const struct asn_oid *oid" "const char *descr" "struct lmodule *mod"
.Ft void
.Fn or_unregister "u_int or_id"
.Ft void *
.Fn buf_alloc "int tx"
.Ft size_t
.Fn buf_size "int tx"
.Ft enum snmpd_input_err
.Fn snmp_input_start "const u_char *buf" "size_t len" "const char *source" \
"struct snmp_pdu *pdu" "int32_t *ip"
.Ft enum snmpd_input_err
.Fn snmp_input_finish "struct snmp_pdu *pdu" "const u_char *rcvbuf" \
"size_t rcvlen" "u_char *sndbuf" "size_t *sndlen" "const char *source" \
"enum snmpd_input_err ierr" "int32_t ip" "void *data"
.Ft void
.Fn snmp_output "struct snmp_pdu *pdu" "u_char *sndbuf" "size_t *sndlen" \
"const char *dest"
.Ft void
.Fn snmp_send_port "const struct asn_oid *port" "struct snmp_pdu *pdu" \
"const struct sockaddr *addr" "socklen_t addrlen"
.Ft void
.Fn snmp_send_trap "const struct asn_oid *oid" "..."
.Ft int
.Fn string_save "struct snmp_value *val" "struct snmp_context *ctx" "ssize_t req_size" "u_char **strp"
.Ft void
.Fn string_commit "struct snmp_context *ctx"
.Ft void
.Fn string_rollback "struct snmp_context *ctx" "u_char **strp"
.Ft int
.Fn string_get "struct snmp_value *val" "const u_char *str" "ssize_t len"
.Ft void
.Fn string_free "struct snmp_context *ctx"
.Ft int
.Fn ip_save "struct snmp_value *val" "struct snmp_context *ctx" "u_char *ipa"
.Ft void
.Fn ip_rollback "struct snmp_context *ctx" "u_char *ipa"
.Ft void
.Fn ip_commit "struct snmp_context *ctx"
.Ft int
.Fn ip_get "struct snmp_value *val" "u_char *ipa"
.Ft int
.Fn oid_save "struct snmp_value *val" "struct snmp_context *ctx" "struct asn_oid *oid"
.Ft void
.Fn oid_rollback "struct snmp_context *ctx" "struct asn_oid *oid"
.Ft void
.Fn oid_commit "struct snmp_context *ctx"
.Ft int
.Fn oid_get "struct snmp_value *val" "const struct asn_oid *oid"
.Ft int
.Fn index_decode "const struct asn_oid *oid" "u_int sub" "u_int code" "..."
.Ft int
.Fn index_compare "const struct asn_oid *oid1" "u_int sub" "const struct asn_oid *oid2"
.Ft int
.Fn index_compare_off "const struct asn_oid *oid1" "u_int sub" "const struct asn_oid *oid2" "u_int off"
.Ft void
.Fn index_append "struct asn_oid *dst" "u_int sub" "const struct asn_oid *src"
.Ft void
.Fn index_append_off "struct asn_oid *dst" "u_int sub" "const struct asn_oid *src" "u_int off"
.Sh DESCRIPTION
The
.Xr snmpd 1
SNMP daemon implements a minimal MIB which consists of the system group, part
of the SNMP MIB, a private configuration MIB, a trap destination table, a
UDP port table, a community table, a module table, a statistics group and
a debugging group. All other MIBs are support through loadable modules.
This allows
.Xr snmpd 1
to use for task, that are not the classical SNMP task.
.Ss MODULE LOADING AND UNLOADING
Modules are loaded by writing to the module table. This table is indexed by
a string, that identfies the module to the daemon. This identifier is used
to select the correct configuration section from the configuration files and
to identify resources allocated to this module. A row in the module table is
created by writing a string of non-zero length to the
.Va begemotSnmpdModulePath
column. This string must be the complete path to the file containing the module.
A module can be unloaded by writing a zero length string to the path column
of an existing row.
.Pp
Modules may depend on each other an hence must be loaded in the correct order.
The dependencies are listed in the corresponding manual pages.
.Pp
Upon loading a module the SNMP daemon expects the module file to a export
a global symbol
.Va config .
This symbol should be a variable of type
.Vt struct snmp_module :
.Bd -literal -offset indent
typedef enum snmpd_proxy_err (*proxy_err_f)(struct snmp_pdu *,
const struct asn_oid *, const struct sockaddr *, socklen_t,
enum snmpd_input_err, int32_t);
struct snmp_module {
const char *comment;
int (*init)(struct lmodule *, int argc, char *argv[]);
int (*fini)(void);
void (*idle)(void);
void (*dump)(void);
void (*config)(void);
void (*start)(void);
proxy_err_f proxy;
const struct snmp_node *tree;
u_int tree_size;
void (*loading)(const struct lmodule *, int);
};
.Ed
.Pp
This structure must be statically initialized and its fields have the
following functions:
.Bl -tag -width ".It Va tree_size"
.It Va comment
This is a string that will be visible in the module table. It should give
some hint about the function of this module.
.It Va init
This function is called upon loading the module. The module pointer should
be stored by the module because it is needed in other calls and the
argument vector will contain the arguments to this module from the daemons
command line. This function should return 0 if everything is ok or an
UNIX error code (see
.Xr errno 3 ).
Once the function returns 0, the
.Va fini
function is called when the module is unloaded.
.It Va fini
The module is unloaded. This gives the module a chance to free resources that
are not automatically freed. Be sure to free all memory, because daemons tend
to run very long. This function pointer may be
.Li NULL
if it is not needed.
.It Va idle
If this function pointer is not
.Li NULL ,
the function pointed to by it is called whenever the daemon is going
to wait for an event. Try to avoid using this feature.
.It Va dump
Whenever the daemon receives a
.Li SIGUSR1
it dumps it internal state via
.Xr syslog 3 .
If the
.Va dump
field is not
.Li NULL
it is called by the daemon to dump the state of the module.
.It Va config
Whenever the daemon receives a
.Li SIGHUP
signal it re-reads its configuration file.
If the
.Va config
field is not
.Li NULL
it is called after reading the configuration file to give the module a chance
to adapt to the new configuration.
.It Va start
If not
.Li NULL
this function is called after successful loading and initializing the module
to start its actual operation.
.It Va proxy
If the daemon receives a PDU and that PDU has a community string who's
community was registered by this module and
.Va proxy
is not
.Li NULL
than this function is called to handle the PDU.
.It Va tree
This is a pointer to the node array for the MIB tree implemented by this module.
.It Va tree_size
This is the number of nodes in
.Va tree .
.It Va loading
If this pointer is not
.Li NULL
it is called whenever another module was loaded or unloaded. It gets a
pointer to that module and a flag that is 0 for unloading and 1 for loading.
.El
.Pp
When everything is ok, the daemon merges the module's MIB tree into its current
global tree, calls the modules
.Fn init
function. If this function returns an error, the modules MIB tree is removed from
the global one and the module is unloaded. If initialisation is successful,
the modules
.Fn start
function is called.
After it returns the
.Fn loaded
functions of all modules (including the loaded one) are called.
.Pp
When the module is unloaded, its MIB tree is removed from the global one,
the communities, request id ranges, running timers and selected file
descriptors are released, the
.Fn fini
function is called, the module file is unloaded and the
.Fn loaded
functions of all other modules are called.
.Ss IMPLEMENTING TABLES
There are a number of macros designed to help implementing SNMP tables.
A problem while implementing a table is the support for the GETNEXT operator.
The GETNEXT operation has to find out whether, given an arbitrary OID, the
lessest table row, that has an OID higher than the given OID. The easiest way
to do this is to keep the table as an ordered list of structures each one
of which contains an OID that is the index of the table row. This allows easy
removal, insertion and search.
.Pp
The helper macros assume, that the table is organized as a TAILQ (see
.Xr queue 3
and each structure contains a
.Vt struct asn_oid
that is used as index.
For simple tables with only a integer or unsigned index, an alternate form
of the macros is available, that presume the existence of an integer or
unsigned field as index field.
.Pp
The macros have name of the form
.Bd -literal -offset indent
{INSERT,FIND,NEXT}_OBJECT_{OID,INT}[_LINK[_INDEX]]
.Ed
.Pp
The
.Fn INSERT_*
macros are used in the SET operation to insert a new table row into the table.
The
.Fn FIND_*
macros are used in the GET operation to find a specific row in the table.
The
.Fn NEXT_*
macros are used in the GETNEXT operation to find the next row in the table.
The last two macros return a pointer to the row structure if a row is found,
.Li NULL
otherwise.
The macros
.Fn *_OBJECT_OID_*
assume the existence of a
.Vt struct asn_oid
that is used as index, the macros
.Fn *_OBJECT_INT_*
assume the existance of an unsigned integer field that is used as index.
.Pp
The macros
.Fn *_INDEX
allow the explicit naming of the index field in the parameter
.Fa INDEX ,
whereas the other macros assume that this field is named
.Va index .
The macros
.Fn *_LINK_*
allow the explicit naming of the link field of the tail queues, the others
assume that the link field is named
.Va link .
Explicitely naming the link field may be necessary if the same structures
are held in two or more different tables.
.Pp
The arguments to the macros are as follows:
.Bl -tag -width "INDEX"
.It Fa PTR
A pointer to the new structure to be inserted into the table.
.It Fa LIST
A pointer to the tail queue head.
.It Fa LINK
The name of the link field in the row structure.
.It Fa INDEX
The name of the index field in the row structure.
.It Fa OID
Must point to the
.Va var
field of the
.Fa value
argument to the node operation callback. This is the OID to search for.
.It Fa SUB
This is the index of the start of the table index in the OID pointed to
by
.Fa OID .
This is usually the same as the
.Fa sub
argument to the node operation callback.
.El
.Ss DAEMON TIMESTAMPS
The variable
.Va this_tick
contains the tick (there are 100 SNMP ticks in a second) when
the current PDU processing was started.
The variable
.Va start_tick
contains the tick when the daemon was started.
The function
.Fn get_ticks
returns the current tick. The number of ticks since the daemon was started
is
.Bd -literal -offset indent
get_ticks() - start_tick
.Ed
.Ss THE SYSTEM GROUP
The scalar fields of the system group are held in the global variable
.Va systemg :
.Bd -literal -offset indent
struct systemg {
u_char *descr;
struct asn_oid object_id;
u_char *contact;
u_char *name;
u_char *location;
u_int32_t services;
u_int32_t or_last_change;
};
.Ed
.Ss COMMUNITIES
The SNMP daemon implements a community table. On recipte of a request message
the community string in that message is compared to each of the community
strings in that table, if a match is found, the global variable
.Va community
is set to the community identifier for that community. Community identifiers
are unsigned integers. For the three standard communities there are three
constants defined:
.Bd -literal -offset indent
#define COMM_INITIALIZE 0
#define COMM_READ 1
#define COMM_WRITE 2
.Ed
.Pp
.Va community
is set to
.Li COMM_INITIALIZE
while the assignments in the configuration file are processed. To
.Li COMM_READ
or
.Li COMM_WRITE
when the community strings for the read-write or read-only community are found
in the incoming PDU.
.Pp
Modules can define additional communities. This may be necessary to provide
transport proxying (a PDU received on one communication link is proxied to
another link) or to implement non-UDP access points to SNMP. A new
community is defined with the function
.Fn comm_define .
It takes the following parameters:
.Bl -tag -width ".It Fa descr"
.It Fa priv
This is an integer identifying the community to the module. Each module has
its own namespace with regard to this parameter. The community table is
indexed with the module name and this identifier.
.It Fa descr
This is a string providing a human readable description of the community.
It is visible in the community table.
.It Fa mod
This is the module defining the community.
.It Fa str
This is the initial community string.
.El
.Pp
The function returns a globally unique community identifier. If a PDU is
received who's community string matches, this identifier is set into the global
.Va community .
.Pp
The function
.Fn comm_string
returns the current community string for the given community.
.Pp
All communities defined by a module are automatically released when the module
is unloaded.
.Ss WELL KNOWN OIDS
The global variable
.Va oid_zeroDotZero
contains the OID 0.0.
.Ss REQUEST ID RANGES
For modules that implement SNMP client functions besides SNMP agent functions
it may be necessary to identify SNMP requests by their identifier to allow
easier routing of responses to the correct sub-system. Request id ranges
provide a way to aquire globally non-overlapping sub-ranges of the entire
31-bit id range.
.Pp
A request id range is allocated with
.Fn reqid_allocate .
The arguments are: the size of the range and the module allocating the range.
For example, the call
.Bd -literal -offset indent
id = reqid_allocate(1000, module);
.Ed
.Pp
allocates a range of 1000 request ids. The function returns the request
id range identifier or 0 if there is not enough identifier space.
The function
.Fn reqid_base
returns the lowest request id in the given range.
.Pp
Request id are allocated starting at the lowest one linear throughout the range.
If the client application may have a lot of outstanding request the range
must be large enough so that an id is not reused until it is really expired.
.Fn reqid_next
returns the sequentially next id in the range.
.Pp
The function
.Fn reqid_istype
checks whether the request id
.Fa reqid
is withing the range identified by
.Fa type .
The function
.Fn reqid_type
returns the range identifier for the given
.Fa reqid
or 0 if the request id is in none of the ranges.
.Ss TIMERS
The SNMP daemon supports an arbitrary number of timers with SNMP tick granularity.
The function
.Fn timer_start
arranges for the callback
.Fa func
to be called with the argument
.Fa uarg
after
.Fa ticks
SNMP ticks have expired.
.Fa mod
is the module that starts the timer. Timers are one-shot, they are not
restarted. The function returns a timer identifier that can be used to
stop the timer via
.Fn timer_stop .
If a module is unloaded all timers started by the module that have not expired
yet are stopped.
.Ss FILE DESCRIPTOR SUPPORT
A module may need to get input from socket file descriptors without blocking
the daemon (for example to implement alternative SNMP transports).
.Pp
The function
.Fn fd_select
causes the callback function
.Fa func
to be called with the file descriptor
.Fa fd
and the user argument
.Fa uarg
whenever the file descriptor
.Fa fd
can be red or has a close condition. If the file descriptor is not in
non-blocking mode, it is set to non-blocking mode. If the callback is not
needed anymore,
.Fn fd_deselect
may be called with the value returned from
.Fn fd_select .
All file descriptors selected by a module are automatically deselected when
the module is unloaded.
.Pp
To temporarily suspend the file descriptor registration
.Fn fd_suspend
can be called. This also causes the file descriptor to be switched back to
blocking mode if it was blocking prior the call to
.Fn fd_select .
This is necessary to do synchronuous input on a selected socket.
The effect of
.Fn fd_suspend
can be undone with
.Fn fd_resume .
.Ss OBJECT RESOURCES
The system group contains an object resource table. A module may create
an entry in this table by calling
.Fn or_register
with the
.Fa oid
to be registered, a textual description in
.Fa str
and a pointer to the module
.Fa mod .
The registration can be removed with
.Fn or_unregister .
All registrations of a module are automatically removed if the module is
unloaded.
.Ss TRANSMIT AND RECEIVE BUFFERS
A buffer is allocated via
.Fn buf_alloc .
The argument must be 1 for transmit and 0 for receive buffers. The function
may return
.Li NULL
if there is no memory available. The current buffersize can be obtained with
.Fn buf_size .
.Sh PROCESSING PDUS
For modules that need to do their own PDU processing (for example for proxying)
the following functions are available:
.Pp
Function
.Fn snmp_input_start
decodes the PDU, searches the community, and sets the global
.Va this_tick .
It returns one of the following error codes:
.Bl -tag -width ".It Er SNMPD_INPUT_VALBADLEN"
.It Er SNMPD_INPUT_OK
Everything ok, continue with processing.
.It Er SNMPD_INPUT_FAILED
The PDU could not be decoded, has a wrong version or an unknown
community string.
.It Er SNMPD_INPUT_VALBADLEN
A SET PDU had a value field in a binding with a wrong length field in an
ASN.1 header.
.It Er SNMPD_INPUT_VALRANGE
A SET PDU had a value field in a binding with a value that is out of range
for the given ASN.1 type.
.It Er SNMPD_INPUT_VALBADENC
A SET PDU had a value field in a binding with wrong ASN.1 encoding.
.El
.Pp
The function
.Fn snmp_input_finish
does the other half of processing: if
.Fn snmp_input_start
did not return OK, tries to construct an error response. If the start was OK,
it calls the correct function from
.Xr bsnmpagent
to execute the request and depending on the outcome constructs a response or
error response PDU or ignores the request PDU. It returns either
.Er SNMPD_INPUT_OK
or
.Er SNMPD_INPUT_FAILED .
In the first case a response PDU was constructed and should be sent.
.Pp
The function
.Fn snmp_output
takes a PDU and encodes it.
.Pp
The function
.Fn snmp_send_port
takes a PDU, encodes it and sends it through the given port (identified by
the index in the port table) to the given address.
.Pp
The function
.Fn snmp_send_trap
sends a trap to all trap destinations. The arguments are the
.Fa oid
identifying the trap and a NULL-terminated list of
.Vt struct snmp_value
pointers that are to be inserted into the trap binding list.
.Ss SIMPLE ACTION SUPPORT
For simple scalar variables that need no dependencies a number of support
functions is available to handle the set, commit, rollback and get.
.Pp
The following functions are used for OCTET STRING scalars, either NUL terminated
or not:
.Bl -tag -width "XXXXXXXXX"
.It Fn string_save
should be called for SNMP_OP_SET.
.Fa value
and
.Fa ctx
are the resp\&. arguments to the node callback.
.Fa valp
is a pointer to the pointer that holds the current value and
.Fa req_size
should be -1 if any size of the string is acceptable or a number larger or
equal zero if the string must have a specific size. The function saves
the old value in the scratch area (note, that any initial value must have
been allocated by
.Xr malloc 3 ),
allocates a new string, copies over the new value, NUL-terminates it and
sets the new current value.
.It Fn string_commit
simply frees the saved old value in the scratch area.
.It Fn string_rollback
frees the new value, and puts back the old one.
.It Fn string_get
is used for GET or GETNEXT. If
.Fa len
is -1, the length is computed via
.Xr strlen 3
from the current string value. If the current value is NULL,
a OCTET STRING of zero length is returned.
.It Fn string_free
must be called if either rollback or commit fails to free the saved old value.
.El
.Pp
The following functions are used to process scalars of type IP-address:
.Bl -tag -width "XXXXXXXXX"
.It Fn ip_save
Saves the current value in the scratch area and sets the new value from
.Fa valp .
.It Fn ip_commit
Does nothing.
.It Fn ip_rollback
Restores the old IP address from the scratch area.
.It Fn ip_get
Retrieves the IP current address.
.El
.Pp
The following functions handle OID-typed variables:
.Bl -tag -width "XXXXXXXXX"
.It Fn oid_save
Saves the current value in the scratch area by allocating a
.Vt struct asn_oid
with
.Xr malloc 3
and sets the new value from
.Fa oid .
.It Fn oid_commit
Frees the old value in the scratch area.
.It Fn oid_rollback
Restores the old OID from the scratch area and frees the old OID.
.It Fn oid_get
Retrieves the OID
.El
.Ss TABLE INDEX HANDLING
The following functions help in handling table indexes:
.Bl -tag -width "XXXXXXXXX"
.It Fn index_decode
Decodes the index part of the OID. The parameter
.Fa oid
must be a pointer to the
.Va var
field of the
.Fa value
argument of the node callback. The
.Fa sub
argument must be the index of the start of the index in the OID (this is
the
.Fa sub
argument to the node callback).
.Fa code
is the index expression (parameter
.Fa idx
to the node callback).
These parameters are followed by parameters depending on the syntax of the index
elements as follows:
.Bl -tag -width ".It Li OCTET STRING"
.It Li INTEGER
.Vt int32_t *
expected as argument.
.It Li COUNTER64
.Vt u_int64_t *
expected as argument. Note, that this syntax is illegal for indexes.
.It Li OCTET STRING
A
.Vt u_char **
and a
.Vt size_t *
expected as arguments. A buffer is allocated to hold the decoded string.
.It Li OID
A
.Vt struct asn_oid *
is expected as argument.
.It Li IP ADDRESS
A
.Vt u_int8_t *
expected as argument that points to a buffer of at least four byte.
.It Li COUNTER, GAUGE, TIMETICKS
A
.Vt u_int32_t
expected.
.It Li NULL
No argument expected.
.El
.It Fn index_compare
compares the current variable with an OID.
.Fa oid1
and
.Fa sub
come from the node callback arguments
.Fa value->var
and
.Fa sub
resp.
.Fa oid2
is the OID to compare to. The function returns -1, 0, +1 when the
variable is lesser, equal, higher to the given OID.
.Fa oid2
must contain only the index part of the table column.
.It Fn index_compare_off
is equivalent to
.Fn index_compare
except that it takes an additional parameter
.Fa off
that causes it to ignore the first
.Fa off
components of both indexes.
.It Fn index_append
appends OID
.Fa src
beginning at position
.Fa sub
to
.Fa dst .
.It Fn index_append_off
appends OID
.Fa src
beginning at position
.Fa off
to
.Fa dst
beginning at position
.Fa sub
+
.Fa off .
.El
.Sh SEE ALSO
.Xr snmpd 1 ,
.Xr gensnmptree 1 ,
.Xr bsnmplib 3
.Xr bsnmpclient 3 ,
.Xr bsnmpagent 3
.Sh STANDARDS
This implementation conforms to the applicable IETF RFCs and ITU-T
recommendations.
.Sh AUTHORS
.An Hartmut Brandt Aq brandt@fokus.gmd.de

View File

@ -0,0 +1,363 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/snmpmod.h,v 1.23 2003/01/28 13:44:35 hbb Exp $
*
* SNMP daemon data and functions exported to modules.
*/
#ifndef snmpmod_h_
#define snmpmod_h_
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include "asn1.h"
#include "snmp.h"
#include "snmpagent.h"
#define MAX_MOD_ARGS 16
/*
* These macros help to handle object lists for SNMP tables. They use
* tail queues to hold the objects in ascending order in the list.
* ordering can be done either on an integer/unsigned field or and asn_oid.
*/
#define INSERT_OBJECT_OID_LINK_INDEX(PTR, LIST, LINK, INDEX) do { \
__typeof (PTR) _lelem; \
\
TAILQ_FOREACH(_lelem, (LIST), LINK) \
if (asn_compare_oid(&_lelem->INDEX, &(PTR)->INDEX) > 0) \
break; \
if (_lelem == NULL) \
TAILQ_INSERT_TAIL((LIST), (PTR), LINK); \
else \
TAILQ_INSERT_BEFORE(_lelem, (PTR), LINK); \
} while(0)
#define INSERT_OBJECT_INT_LINK_INDEX(PTR, LIST, LINK, INDEX) do { \
__typeof (PTR) _lelem; \
\
TAILQ_FOREACH(_lelem, (LIST), LINK) \
if ((asn_subid_t)_lelem->INDEX > (asn_subid_t)(PTR)->INDEX)\
break; \
if (_lelem == NULL) \
TAILQ_INSERT_TAIL((LIST), (PTR), LINK); \
else \
TAILQ_INSERT_BEFORE(_lelem, (PTR), LINK); \
} while(0)
#define FIND_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({ \
__typeof (TAILQ_FIRST(LIST)) _lelem; \
\
TAILQ_FOREACH(_lelem, (LIST), LINK) \
if (index_compare(OID, SUB, &_lelem->INDEX) == 0) \
break; \
(_lelem); \
})
#define NEXT_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({ \
__typeof (TAILQ_FIRST(LIST)) _lelem; \
\
TAILQ_FOREACH(_lelem, (LIST), LINK) \
if (index_compare(OID, SUB, &_lelem->INDEX) < 0) \
break; \
(_lelem); \
})
#define FIND_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({ \
__typeof (TAILQ_FIRST(LIST)) _lelem; \
\
if ((OID)->len - SUB != 1) \
_lelem = NULL; \
else \
TAILQ_FOREACH(_lelem, (LIST), LINK) \
if ((OID)->subs[SUB] == (asn_subid_t)_lelem->INDEX)\
break; \
(_lelem); \
})
#define NEXT_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({ \
__typeof (TAILQ_FIRST(LIST)) _lelem; \
\
if ((OID)->len - SUB == 0) \
_lelem = TAILQ_FIRST(LIST); \
else \
TAILQ_FOREACH(_lelem, (LIST), LINK) \
if ((OID)->subs[SUB] < (asn_subid_t)_lelem->INDEX)\
break; \
(_lelem); \
})
/*
* Macros for the case where the index field is called 'index'
*/
#define INSERT_OBJECT_OID_LINK(PTR, LIST, LINK) \
INSERT_OBJECT_OID_LINK_INDEX(PTR, LIST, LINK, index)
#define INSERT_OBJECT_INT_LINK(PTR, LIST, LINK) do { \
INSERT_OBJECT_INT_LINK_INDEX(PTR, LIST, LINK, index)
#define FIND_OBJECT_OID_LINK(LIST, OID, SUB, LINK) \
FIND_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, index)
#define NEXT_OBJECT_OID_LINK(LIST, OID, SUB, LINK) \
NEXT_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, index)
#define FIND_OBJECT_INT_LINK(LIST, OID, SUB, LINK) \
FIND_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, index)
#define NEXT_OBJECT_INT_LINK(LIST, OID, SUB, LINK) \
NEXT_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, index)
/*
* Macros for the case where the index field is called 'index' and the
* link field 'link'.
*/
#define INSERT_OBJECT_OID(PTR, LIST) \
INSERT_OBJECT_OID_LINK_INDEX(PTR, LIST, link, index)
#define INSERT_OBJECT_INT(PTR, LIST) \
INSERT_OBJECT_INT_LINK_INDEX(PTR, LIST, link, index)
#define FIND_OBJECT_OID(LIST, OID, SUB) \
FIND_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, link, index)
#define FIND_OBJECT_INT(LIST, OID, SUB) \
FIND_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, link, index)
#define NEXT_OBJECT_OID(LIST, OID, SUB) \
NEXT_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, link, index)
#define NEXT_OBJECT_INT(LIST, OID, SUB) \
NEXT_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, link, index)
struct lmodule;
/* ticks when program and current packet was started */
extern u_int32_t this_tick;
extern u_int32_t start_tick;
u_int32_t get_ticks(void);
/*
* Return code for proxy function
*/
enum snmpd_proxy_err {
/* proxy code will process the PDU */
SNMPD_PROXY_OK,
/* proxy code does not process PDU */
SNMPD_PROXY_REJ,
/* drop this PDU */
SNMPD_PROXY_DROP,
/* drop because of bad community */
SNMPD_PROXY_BADCOMM,
/* drop because of bad community use */
SNMPD_PROXY_BADCOMMUSE
};
/*
* Input handling
*/
enum snmpd_input_err {
/* proceed with packet */
SNMPD_INPUT_OK,
/* fatal error in packet, ignore it */
SNMPD_INPUT_FAILED,
/* value encoding has wrong length in a SET operation */
SNMPD_INPUT_VALBADLEN,
/* value encoding is out of range */
SNMPD_INPUT_VALRANGE,
/* value has bad encoding */
SNMPD_INPUT_VALBADENC,
};
/*
* Every loadable module must have one of this structures with
* the external name 'config'.
*/
struct snmp_module {
/* a comment describing what this module implements */
const char *comment;
/* the initialisation function */
int (*init)(struct lmodule *, int argc, char *argv[]);
/* the finalisation function */
int (*fini)(void);
/* the idle function */
void (*idle)(void);
/* the dump function */
void (*dump)(void);
/* re-configuration function */
void (*config)(void);
/* start operation */
void (*start)(void);
/* proxy a PDU */
enum snmpd_proxy_err (*proxy)(struct snmp_v1_pdu *,
const struct asn_oid *, const struct sockaddr *, socklen_t,
enum snmpd_input_err, int32_t);
/* the tree this module is going to server */
const struct snmp_node *tree;
u_int tree_size;
/* function called, when another module was unloaded/loaded */
void (*loading)(const struct lmodule *, int);
};
/*
* Stuff exported to modules
*/
/*
* The system group.
*/
struct systemg {
u_char *descr;
struct asn_oid object_id;
u_char *contact;
u_char *name;
u_char *location;
u_int32_t services;
u_int32_t or_last_change;
};
extern struct systemg systemg;
/*
* Community support.
*
* We have 2 fixed communities for SNMP read and write access. Modules
* can create their communities dynamically. They are deleted automatically
* if the module is unloaded.
*/
#define COMM_INITIALIZE 0
#define COMM_READ 1
#define COMM_WRITE 2
u_int comm_define(u_int, const char *descr, struct lmodule *, const char *str);
const char * comm_string(u_int);
/* community for current packet */
extern u_int community;
/*
* Well known OIDs
*/
extern const struct asn_oid oid_zeroDotZero;
/*
* Request ID ranges.
*
* A module can request a range of request ids and associate them with a
* type field. All ranges are deleted if a module is unloaded.
*/
u_int reqid_allocate(int size, struct lmodule *);
int32_t reqid_next(u_int type);
int32_t reqid_base(u_int type);
int reqid_istype(int32_t reqid, u_int type);
u_int reqid_type(int32_t reqid);
/*
* Timers.
*/
void *timer_start(u_int, void (*)(void *), void *, struct lmodule *);
void timer_stop(void *);
/*
* File descriptors
*/
void *fd_select(int, void (*)(int, void *), void *, struct lmodule *);
void fd_deselect(void *);
void fd_suspend(void *);
int fd_resume(void *);
/*
* Object resources
*/
u_int or_register(const struct asn_oid *, const char *, struct lmodule *);
void or_unregister(u_int);
/*
* Buffers
*/
void *buf_alloc(int tx);
size_t buf_size(int tx);
/* decode PDU and find community */
enum snmpd_input_err snmp_input_start(const u_char *, size_t, const char *,
struct snmp_v1_pdu *, int32_t *);
/* process the pdu. returns either _OK or _FAILED */
enum snmpd_input_err snmp_input_finish(struct snmp_pdu *, const u_char *,
size_t, u_char *, size_t *, const char *, enum snmpd_input_err, int32_t,
void *);
void snmp_output(struct snmp_v1_pdu *, u_char *, size_t *, const char *);
void snmp_send_port(const struct asn_oid *, struct snmp_v1_pdu *,
const struct sockaddr *, socklen_t);
/* sending traps */
void snmp_send_trap(const struct asn_oid *, ...);
/*
* Action support
*/
int string_save(struct snmp_value *, struct snmp_context *, ssize_t, u_char **);
void string_commit(struct snmp_context *);
void string_rollback(struct snmp_context *, u_char **);
int string_get(struct snmp_value *, const u_char *, ssize_t);
void string_free(struct snmp_context *);
int ip_save(struct snmp_value *, struct snmp_context *, u_char *);
void ip_rollback(struct snmp_context *, u_char *);
void ip_commit(struct snmp_context *);
int ip_get(struct snmp_value *, u_char *);
int oid_save(struct snmp_value *, struct snmp_context *, struct asn_oid *);
void oid_rollback(struct snmp_context *, struct asn_oid *);
void oid_commit(struct snmp_context *);
int oid_get(struct snmp_value *, const struct asn_oid *);
int index_decode(const struct asn_oid *oid, u_int sub, u_int code, ...);
int index_compare(const struct asn_oid *, u_int, const struct asn_oid *);
int index_compare_off(const struct asn_oid *, u_int, const struct asn_oid *,
u_int);
void index_append(struct asn_oid *, u_int, const struct asn_oid *);
void index_append_off(struct asn_oid *, u_int, const struct asn_oid *, u_int);
#endif

475
contrib/bsnmp/snmpd/trap.c Normal file
View File

@ -0,0 +1,475 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Redistribution of this software and documentation 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 or documentation 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
* AND ITS 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
* FRAUNHOFER FOKUS OR ITS 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/trap.c,v 1.5 2003/01/28 13:44:35 hbb Exp $
*
* TrapSinkTable
*/
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <syslog.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "snmpmod.h"
#include "snmpd.h"
#include "tree.h"
#include "oid.h"
struct trapsink_list trapsink_list = TAILQ_HEAD_INITIALIZER(trapsink_list);
static const struct asn_oid oid_begemotTrapSinkTable =
OIDX_begemotTrapSinkTable;
static const struct asn_oid oid_sysUpTime = OIDX_sysUpTime;
static const struct asn_oid oid_snmpTrapOID = OIDX_snmpTrapOID;
struct trapsink_dep {
struct snmp_dependency dep;
u_int set;
u_int status;
u_char comm[SNMP_COMMUNITY_MAXLEN + 1];
u_int version;
u_int rb;
u_int rb_status;
u_int rb_version;
u_char rb_comm[SNMP_COMMUNITY_MAXLEN + 1];
};
enum {
TDEP_STATUS = 0x0001,
TDEP_COMM = 0x0002,
TDEP_VERSION = 0x0004,
TDEP_CREATE = 0x0001,
TDEP_MODIFY = 0x0002,
TDEP_DESTROY = 0x0004,
};
static int
trapsink_create(struct trapsink_dep *tdep)
{
struct trapsink *t;
struct sockaddr_in sa;
if ((t = malloc(sizeof(*t))) == NULL)
return (SNMP_ERR_RES_UNAVAIL);
t->index = tdep->dep.idx;
t->status = TRAPSINK_NOT_READY;
t->comm[0] = '\0';
t->version = TRAPSINK_V2;
if ((t->socket = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
syslog(LOG_ERR, "socket(UDP): %m");
free(t);
return (SNMP_ERR_RES_UNAVAIL);
}
(void)shutdown(t->socket, SHUT_RD);
sa.sin_len = sizeof(sa);
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = htonl((t->index.subs[0] << 24) |
(t->index.subs[1] << 16) | (t->index.subs[2] << 8) |
(t->index.subs[3] << 0));
sa.sin_port = htons(t->index.subs[4]);
if (connect(t->socket, (struct sockaddr *)&sa, sa.sin_len) == -1) {
syslog(LOG_ERR, "connect(%s,%u): %m",
inet_ntoa(sa.sin_addr), ntohl(sa.sin_port));
(void)close(t->socket);
free(t);
return (SNMP_ERR_GENERR);
}
if (tdep->set & TDEP_VERSION)
t->version = tdep->version;
if (tdep->set & TDEP_COMM)
strcpy(t->comm, tdep->comm);
if (t->comm[0] != '\0')
t->status = TRAPSINK_NOT_IN_SERVICE;
/* look whether we should activate */
if (tdep->status == 4) {
if (t->status == TRAPSINK_NOT_READY) {
if (t->socket != -1)
(void)close(t->socket);
free(t);
return (SNMP_ERR_INCONS_VALUE);
}
t->status = TRAPSINK_ACTIVE;
}
INSERT_OBJECT_OID(t, &trapsink_list);
tdep->rb |= TDEP_CREATE;
return (SNMP_ERR_NOERROR);
}
static void
trapsink_free(struct trapsink *t)
{
TAILQ_REMOVE(&trapsink_list, t, link);
if (t->socket != -1)
(void)close(t->socket);
free(t);
}
static int
trapsink_modify(struct trapsink *t, struct trapsink_dep *tdep)
{
tdep->rb_status = t->status;
tdep->rb_version = t->version;
strcpy(tdep->rb_comm, t->comm);
if (tdep->set & TDEP_STATUS) {
/* if we are active and should move to not_in_service do
* this first */
if (tdep->status == 2 && tdep->rb_status == TRAPSINK_ACTIVE) {
t->status = TRAPSINK_NOT_IN_SERVICE;
tdep->rb |= TDEP_MODIFY;
}
}
if (tdep->set & TDEP_VERSION)
t->version = tdep->version;
if (tdep->set & TDEP_COMM)
strcpy(t->comm, tdep->comm);
if (tdep->set & TDEP_STATUS) {
/* if we were inactive and should go active - do this now */
if (tdep->status == 1 && tdep->rb_status != TRAPSINK_ACTIVE) {
if (t->comm[0] == '\0') {
t->status = tdep->rb_status;
t->version = tdep->rb_version;
strcpy(t->comm, tdep->rb_comm);
return (SNMP_ERR_INCONS_VALUE);
}
t->status = TRAPSINK_ACTIVE;
tdep->rb |= TDEP_MODIFY;
}
}
return (SNMP_ERR_NOERROR);
}
static int
trapsink_unmodify(struct trapsink *t, struct trapsink_dep *tdep)
{
if (tdep->set & TDEP_STATUS)
t->status = tdep->rb_status;
if (tdep->set & TDEP_VERSION)
t->version = tdep->rb_version;
if (tdep->set & TDEP_COMM)
strcpy(t->comm, tdep->rb_comm);
return (SNMP_ERR_NOERROR);
}
static void
trapsink_finish(struct snmp_context *ctx __unused, int fail, void *arg)
{
struct trapsink *t = arg;
if (!fail)
trapsink_free(t);
}
static int
trapsink_destroy(struct snmp_context *ctx, struct trapsink *t,
struct trapsink_dep *tdep)
{
if (snmp_set_atfinish(ctx, trapsink_finish, t))
return (SNMP_ERR_RES_UNAVAIL);
t->status = TRAPSINK_DESTROY;
tdep->rb_status = t->status;
tdep->rb |= TDEP_DESTROY;
return (SNMP_ERR_NOERROR);
}
static int
trapsink_undestroy(struct trapsink *t, struct trapsink_dep *tdep)
{
t->status = tdep->rb_status;
return (SNMP_ERR_NOERROR);
}
static int
trapsink_dep(struct snmp_context *ctx, struct snmp_dependency *dep,
enum snmp_depop op)
{
struct trapsink_dep *tdep = (struct trapsink_dep *)dep;
struct trapsink *t;
t = FIND_OBJECT_OID(&trapsink_list, &dep->idx, 0);
switch (op) {
case SNMP_DEPOP_COMMIT:
if (tdep->set & TDEP_STATUS) {
switch (tdep->status) {
case 1:
case 2:
if (t == NULL)
return (SNMP_ERR_INCONS_VALUE);
return (trapsink_modify(t, tdep));
case 4:
case 5:
if (t != NULL)
return (SNMP_ERR_INCONS_VALUE);
return (trapsink_create(tdep));
case 6:
if (t == NULL)
return (SNMP_ERR_NOERROR);
return (trapsink_destroy(ctx, t, tdep));
}
} else if (tdep->set != 0)
return (trapsink_modify(t, tdep));
return (SNMP_ERR_NOERROR);
case SNMP_DEPOP_ROLLBACK:
if (tdep->rb & TDEP_CREATE) {
trapsink_free(t);
return (SNMP_ERR_NOERROR);
}
if (tdep->rb & TDEP_MODIFY)
return (trapsink_unmodify(t, tdep));
if(tdep->rb & TDEP_DESTROY)
return (trapsink_undestroy(t, tdep));
return (SNMP_ERR_NOERROR);
}
abort();
}
int
op_trapsink(struct snmp_context *ctx, struct snmp_value *value,
u_int sub, u_int iidx, enum snmp_op op)
{
struct trapsink *t;
u_char ipa[4];
int32_t port;
struct asn_oid idx;
struct trapsink_dep *tdep;
u_char *p;
t = NULL; /* gcc */
switch (op) {
case SNMP_OP_GETNEXT:
if ((t = NEXT_OBJECT_OID(&trapsink_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NOSUCHNAME);
index_append(&value->var, sub, &t->index);
break;
case SNMP_OP_GET:
if ((t = FIND_OBJECT_OID(&trapsink_list, &value->var, sub)) == NULL)
return (SNMP_ERR_NOSUCHNAME);
break;
case SNMP_OP_SET:
if (index_decode(&value->var, sub, iidx, ipa, &port) ||
port == 0 || port > 65535)
return (SNMP_ERR_NO_CREATION);
t = FIND_OBJECT_OID(&trapsink_list, &value->var, sub);
asn_slice_oid(&idx, &value->var, sub, value->var.len);
tdep = (struct trapsink_dep *)snmp_dep_lookup(ctx,
&oid_begemotTrapSinkTable, &idx,
sizeof(*tdep), trapsink_dep);
if (tdep == NULL)
return (SNMP_ERR_RES_UNAVAIL);
switch (value->var.subs[sub - 1]) {
case LEAF_begemotTrapSinkStatus:
if (tdep->set & TDEP_STATUS)
return (SNMP_ERR_INCONS_VALUE);
switch (value->v.integer) {
case 1:
case 2:
if (t == NULL)
return (SNMP_ERR_INCONS_VALUE);
break;
case 4:
case 5:
if (t != NULL)
return (SNMP_ERR_INCONS_VALUE);
break;
case 6:
break;
default:
return (SNMP_ERR_WRONG_VALUE);
}
tdep->status = value->v.integer;
tdep->set |= TDEP_STATUS;
return (SNMP_ERR_NOERROR);
case LEAF_begemotTrapSinkComm:
if (tdep->set & TDEP_COMM)
return (SNMP_ERR_INCONS_VALUE);
if (value->v.octetstring.len == 0 ||
value->v.octetstring.len > SNMP_COMMUNITY_MAXLEN)
return (SNMP_ERR_WRONG_VALUE);
for (p = value->v.octetstring.octets;
p < value->v.octetstring.octets + value->v.octetstring.len;
p++) {
if (!isascii(*p) || !isprint(*p))
return (SNMP_ERR_WRONG_VALUE);
}
tdep->set |= TDEP_COMM;
strncpy(tdep->comm, value->v.octetstring.octets,
value->v.octetstring.len);
tdep->comm[value->v.octetstring.len] = '\0';
return (SNMP_ERR_NOERROR);
case LEAF_begemotTrapSinkVersion:
if (tdep->set & TDEP_VERSION)
return (SNMP_ERR_INCONS_VALUE);
if (value->v.integer != TRAPSINK_V1 &&
value->v.integer != TRAPSINK_V2)
return (SNMP_ERR_WRONG_VALUE);
tdep->version = value->v.integer;
tdep->set |= TDEP_VERSION;
return (SNMP_ERR_NOERROR);
}
if (t == NULL)
return (SNMP_ERR_INCONS_NAME);
else
return (SNMP_ERR_NOT_WRITEABLE);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
return (SNMP_ERR_NOERROR);
}
switch (value->var.subs[sub - 1]) {
case LEAF_begemotTrapSinkStatus:
value->v.integer = t->status;
break;
case LEAF_begemotTrapSinkComm:
return (string_get(value, t->comm, -1));
case LEAF_begemotTrapSinkVersion:
value->v.integer = t->version;
break;
}
return (SNMP_ERR_NOERROR);
}
void
snmp_send_trap(const struct asn_oid *trap_oid, ...)
{
struct snmp_pdu pdu;
struct trapsink *t;
const struct snmp_value *v;
va_list ap;
u_char *sndbuf;
size_t sndlen;
ssize_t len;
TAILQ_FOREACH(t, &trapsink_list, link) {
if (t->status != TRAPSINK_ACTIVE)
continue;
memset(&pdu, 0, sizeof(pdu));
strcpy(pdu.community, t->comm);
if (t->version == TRAPSINK_V1) {
pdu.version = SNMP_V1;
pdu.type = SNMP_PDU_TRAP;
pdu.enterprise = systemg.object_id;
memcpy(pdu.agent_addr, snmpd.trap1addr, 4);
pdu.generic_trap = trap_oid->subs[trap_oid->len - 1] - 1;
pdu.specific_trap = 0;
pdu.time_stamp = get_ticks() - start_tick;
pdu.nbindings = 0;
} else {
pdu.version = SNMP_V2c;
pdu.type = SNMP_PDU_TRAP2;
pdu.request_id = reqid_next(trap_reqid);
pdu.error_index = 0;
pdu.error_status = SNMP_ERR_NOERROR;
pdu.bindings[0].var = oid_sysUpTime;
pdu.bindings[0].var.subs[pdu.bindings[0].var.len++] = 0;
pdu.bindings[0].syntax = SNMP_SYNTAX_TIMETICKS;
pdu.bindings[0].v.uint32 = get_ticks() - start_tick;
pdu.bindings[1].var = oid_snmpTrapOID;
pdu.bindings[1].var.subs[pdu.bindings[1].var.len++] = 0;
pdu.bindings[1].syntax = SNMP_SYNTAX_OID;
pdu.bindings[1].v.oid = *trap_oid;
pdu.nbindings = 2;
}
va_start(ap, trap_oid);
while ((v = va_arg(ap, const struct snmp_value *)) != NULL)
pdu.bindings[pdu.nbindings++] = *v;
va_end(ap);
if ((sndbuf = buf_alloc(1)) == NULL) {
syslog(LOG_ERR, "trap send buffer: %m");
return;
}
snmp_output(&pdu, sndbuf, &sndlen, "TRAP");
if ((len = send(t->socket, sndbuf, sndlen, 0)) == -1)
syslog(LOG_ERR, "send: %m");
else if ((size_t)len != sndlen)
syslog(LOG_ERR, "send: short write %zu/%zu",
sndlen, (size_t)len);
free(sndbuf);
}
}

View File

@ -0,0 +1,183 @@
#
# Copyright (c) 2001-2003
# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
# All rights reserved.
#
# Author: Harti Brandt <harti@freebsd.org>
#
# Redistribution of this software and documentation 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 or documentation 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.
# 3. Neither the name of the Institute nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
# AND ITS 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
# FRAUNHOFER FOKUS OR ITS 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/tree.def,v 1.34 2002/12/11 15:54:08 hbb Exp $
#
# System group and private Begemot SNMPd MIB.
#
(1 internet
(2 mgmt
(1 mibII
(1 system
#
# The standard System group
#
(1 sysDescr OCTETSTRING op_system_group GET)
(2 sysObjectId OID op_system_group GET)
(3 sysUpTime TIMETICKS op_system_group GET)
(4 sysContact OCTETSTRING op_system_group GET SET)
(5 sysName OCTETSTRING op_system_group GET SET)
(6 sysLocation OCTETSTRING op_system_group GET SET)
(7 sysServices INTEGER op_system_group GET)
(8 sysORLastChange TIMETICKS op_system_group GET)
(9 sysORTable
(1 sysOREntry : INTEGER op_or_table
(1 sysORIndex INTEGER)
(2 sysORID OID GET)
(3 sysORDescr OCTETSTRING GET)
(4 sysORUpTime TIMETICKS GET)
))
)
(11 snmp
(1 snmpInPkts COUNTER op_snmp GET)
(3 snmpInBadVersions COUNTER op_snmp GET)
(4 snmpInBadCommunityNames COUNTER op_snmp GET)
(5 snmpInBadCommunityUses COUNTER op_snmp GET)
(6 snmpInASNParseErrs COUNTER op_snmp GET)
(30 snmpEnableAuthenTraps INTEGER op_snmp GET SET)
(31 snmpSilentDrops COUNTER op_snmp GET)
(32 snmpProxyDrops COUNTER op_snmp GET)
)
))
#
# Private Begemot Stuff
#
(4 private
(1 enterprises
(12325 fokus
(1 begemot
#
# Daemon infrastructure
#
(1 begemotSnmpd
(1 begemotSnmpdObjects
#
# Configuration
#
(1 begemotSnmpdConfig
(1 begemotSnmpdTransmitBuffer INTEGER op_snmpd_config GET SET)
(2 begemotSnmpdReceiveBuffer INTEGER op_snmpd_config GET SET)
(3 begemotSnmpdCommunityDisable INTEGER op_snmpd_config GET SET)
(4 begemotSnmpdTrap1Addr IPADDRESS op_snmpd_config GET SET)
)
(2 begemotTrapSinkTable
(1 begemotTrapSinkEntry : IPADDRESS INTEGER op_trapsink
(1 begemotTrapSinkAddr IPADDRESS)
(2 begemotTrapSinkPort INTEGER)
(3 begemotTrapSinkStatus INTEGER GET SET)
(4 begemotTrapSinkComm OCTETSTRING GET SET)
(5 begemotTrapSinkVersion INTEGER GET SET)
)
)
#
# Port table
#
(4 begemotSnmpdPortTable
(1 begemotSnmpdPortEntry : IPADDRESS INTEGER op_snmp_port
(1 begemotSnmpdPortAddress IPADDRESS)
(2 begemotSnmpdPortPort UNSIGNED32)
(3 begemotSnmpdPortStatus INTEGER GET SET)
))
#
# Community table
#
(5 begemotSnmpdCommunityTable
(1 begemotSnmpdCommunityEntry : OCTETSTRING UNSIGNED32 op_community
(1 begemotSnmpdCommunityModule OCTETSTRING)
(2 begemotSnmpdCommunityIndex UNSIGNED32)
(3 begemotSnmpdCommunityString OCTETSTRING GET SET)
(4 begemotSnmpdCommunityDescr OCTETSTRING GET)
))
#
# Module table
#
(6 begemotSnmpdModuleTable
(1 begemotSnmpdModuleEntry : OCTETSTRING op_modules
(1 begemotSnmpdModuleSection OCTETSTRING)
(2 begemotSnmpdModulePath OCTETSTRING GET SET)
(3 begemotSnmpdModuleComment OCTETSTRING GET)
))
#
# Statistics
#
(7 begemotSnmpdStats
(1 begemotSnmpdStatsNoRxBufs COUNTER op_snmpd_stats GET)
(2 begemotSnmpdStatsNoTxBufs COUNTER op_snmpd_stats GET)
(3 begemotSnmpdStatsInTooLongPkts COUNTER op_snmpd_stats GET)
(4 begemotSnmpdStatsInBadPduTypes COUNTER op_snmpd_stats GET))
#
# Debugging
#
(8 begemotSnmpdDebug
(1 begemotSnmpdDebugDumpPdus INTEGER op_debug GET SET)
(2 begemotSnmpdDebugSnmpTrace UNSIGNED32 op_debug GET SET)
(3 begemotSnmpdDebugSyslogPri INTEGER op_debug GET SET))
#
# Local (UNIX domain) port table
#
(9 begemotSnmpdLocalPortTable
(1 begemotSnmpdLocalPortEntry : OCTETSTRING op_local_port
(1 begemotSnmpdLocalPortPath OCTETSTRING)
(2 begemotSnmpdLocalPortStatus INTEGER GET SET)
))
)
(2 begemotSnmpdDefs
(1 begemotSnmpdAgent
(1 begemotSnmpdAgentFreeBSD OID op_dummy)
)
)
)
))
)
)
(6 snmpV2
(3 snmpModules
(1 snmpMIB
(1 snmpMIBObjects
(4 snmpTrap
(1 snmpTrapOID OID op_snmp_trap)
)
(5 snmpTraps
(1 coldStart OID op_snmp_trap)
(2 warmStart OID op_snmp_trap)
(5 authenticationFailure OID op_snmp_trap)
)
(6 snmpSet
(1 snmpSetSerialNo INTEGER op_snmp_set GET SET)
)
)
)
))
)