From 259ee3d78efad4925d61cb8ab3b25539ee761e00 Mon Sep 17 00:00:00 2001 From: Hartmut Brandt Date: Mon, 10 Nov 2003 09:17:34 +0000 Subject: [PATCH] Add build infrastructure for libbsnmp and the modules. Add the netgraph module for the SNMP daemon. --- lib/libbsnmp/Makefile | 5 + lib/libbsnmp/Makefile.inc | 8 + lib/libbsnmp/libbsnmp/Makefile | 17 + lib/libbsnmp/modules/Makefile | 11 + lib/libbsnmp/modules/Makefile.inc | 16 + lib/libbsnmp/modules/snmp_mibII/Makefile | 19 + lib/libbsnmp/modules/snmp_mibII/genfiles | 20 + lib/libbsnmp/modules/snmp_mibII/mibII_oid.h | 35 + lib/libbsnmp/modules/snmp_mibII/mibII_tree.c | 154 ++ lib/libbsnmp/modules/snmp_mibII/mibII_tree.h | 163 ++ .../snmp_netgraph/BEGEMOT-NETGRAPH.txt | 398 ++++ lib/libbsnmp/modules/snmp_netgraph/Makefile | 15 + lib/libbsnmp/modules/snmp_netgraph/genfiles | 17 + .../modules/snmp_netgraph/netgraph_oid.h | 5 + .../modules/snmp_netgraph/netgraph_tree.c | 30 + .../modules/snmp_netgraph/netgraph_tree.def | 78 + .../modules/snmp_netgraph/netgraph_tree.h | 27 + .../modules/snmp_netgraph/snmp_netgraph.3 | 416 ++++ .../modules/snmp_netgraph/snmp_netgraph.c | 1691 +++++++++++++++++ .../modules/snmp_netgraph/snmp_netgraph.h | 91 + usr.sbin/bsnmpd/modules/Makefile | 11 + usr.sbin/bsnmpd/modules/Makefile.inc | 16 + usr.sbin/bsnmpd/modules/snmp_mibII/Makefile | 19 + .../snmp_netgraph/BEGEMOT-NETGRAPH.txt | 398 ++++ .../bsnmpd/modules/snmp_netgraph/Makefile | 15 + .../modules/snmp_netgraph/netgraph_tree.def | 78 + .../modules/snmp_netgraph/snmp_netgraph.3 | 416 ++++ .../modules/snmp_netgraph/snmp_netgraph.c | 1691 +++++++++++++++++ .../modules/snmp_netgraph/snmp_netgraph.h | 91 + 29 files changed, 5951 insertions(+) create mode 100644 lib/libbsnmp/Makefile create mode 100644 lib/libbsnmp/Makefile.inc create mode 100644 lib/libbsnmp/libbsnmp/Makefile create mode 100644 lib/libbsnmp/modules/Makefile create mode 100644 lib/libbsnmp/modules/Makefile.inc create mode 100644 lib/libbsnmp/modules/snmp_mibII/Makefile create mode 100644 lib/libbsnmp/modules/snmp_mibII/genfiles create mode 100644 lib/libbsnmp/modules/snmp_mibII/mibII_oid.h create mode 100644 lib/libbsnmp/modules/snmp_mibII/mibII_tree.c create mode 100644 lib/libbsnmp/modules/snmp_mibII/mibII_tree.h create mode 100644 lib/libbsnmp/modules/snmp_netgraph/BEGEMOT-NETGRAPH.txt create mode 100644 lib/libbsnmp/modules/snmp_netgraph/Makefile create mode 100644 lib/libbsnmp/modules/snmp_netgraph/genfiles create mode 100644 lib/libbsnmp/modules/snmp_netgraph/netgraph_oid.h create mode 100644 lib/libbsnmp/modules/snmp_netgraph/netgraph_tree.c create mode 100644 lib/libbsnmp/modules/snmp_netgraph/netgraph_tree.def create mode 100644 lib/libbsnmp/modules/snmp_netgraph/netgraph_tree.h create mode 100644 lib/libbsnmp/modules/snmp_netgraph/snmp_netgraph.3 create mode 100644 lib/libbsnmp/modules/snmp_netgraph/snmp_netgraph.c create mode 100644 lib/libbsnmp/modules/snmp_netgraph/snmp_netgraph.h create mode 100644 usr.sbin/bsnmpd/modules/Makefile create mode 100644 usr.sbin/bsnmpd/modules/Makefile.inc create mode 100644 usr.sbin/bsnmpd/modules/snmp_mibII/Makefile create mode 100644 usr.sbin/bsnmpd/modules/snmp_netgraph/BEGEMOT-NETGRAPH.txt create mode 100644 usr.sbin/bsnmpd/modules/snmp_netgraph/Makefile create mode 100644 usr.sbin/bsnmpd/modules/snmp_netgraph/netgraph_tree.def create mode 100644 usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.3 create mode 100644 usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.c create mode 100644 usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.h diff --git a/lib/libbsnmp/Makefile b/lib/libbsnmp/Makefile new file mode 100644 index 00000000000..c639fa8f2fd --- /dev/null +++ b/lib/libbsnmp/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +SUBDIR+= libbsnmp modules + +.include diff --git a/lib/libbsnmp/Makefile.inc b/lib/libbsnmp/Makefile.inc new file mode 100644 index 00000000000..5304ebdf2f1 --- /dev/null +++ b/lib/libbsnmp/Makefile.inc @@ -0,0 +1,8 @@ +# $FreeBSD$ + +SHLIB_MAJOR= 1 +SHLIB_MINOR= 4 + +WARNS?= 6 + +INCSDIR= ${INCLUDEDIR}/bsnmp diff --git a/lib/libbsnmp/libbsnmp/Makefile b/lib/libbsnmp/libbsnmp/Makefile new file mode 100644 index 00000000000..6591567ca61 --- /dev/null +++ b/lib/libbsnmp/libbsnmp/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ +# +# Author: Harti Brandt + +CONTRIB= ${.CURDIR}/../../../contrib/bsnmp/lib +.PATH: ${CONTRIB} + +LIB = bsnmp + +WARNS= 6 +CFLAGS= -I${CONTRIB} + +SRCS= asn1.c snmp.c snmpagent.c snmpclient.c +INCS= asn1.h snmp.h snmpagent.h snmpclient.h +MAN= asn1.3 bsnmplib.3 bsnmpclient.3 bsnmpagent.3 + +.include diff --git a/lib/libbsnmp/modules/Makefile b/lib/libbsnmp/modules/Makefile new file mode 100644 index 00000000000..ad5df5f209b --- /dev/null +++ b/lib/libbsnmp/modules/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../contrib/bsnmp/snmpd + +SUBDIR= snmp_mibII \ + snmp_netgraph + +INCS= snmpmod.h +INCSDIR= ${INCLUDEDIR}/bsnmp + +.include diff --git a/lib/libbsnmp/modules/Makefile.inc b/lib/libbsnmp/modules/Makefile.inc new file mode 100644 index 00000000000..c9d6718cfa2 --- /dev/null +++ b/lib/libbsnmp/modules/Makefile.inc @@ -0,0 +1,16 @@ +# $FreeBSD$ + +NOINSTALLLIB= yes +NOPROFILE= yes + +LIB= snmp_${MOD} +SHLIB_NAME= snmp_${MOD}.so.${SHLIB_MAJOR} + +SRCS:= ${MOD}_oid.h ${MOD}_tree.c ${MOD}_tree.h ${SRCS} + +MIBSDIR= ${SHAREDIR}/bsnmp/mibs +DEFSDIR= ${SHAREDIR}/bsnmp/defs + +FILESGROUPS += DEFS MIBS + +.include "../Makefile.inc" diff --git a/lib/libbsnmp/modules/snmp_mibII/Makefile b/lib/libbsnmp/modules/snmp_mibII/Makefile new file mode 100644 index 00000000000..7fa524a93c8 --- /dev/null +++ b/lib/libbsnmp/modules/snmp_mibII/Makefile @@ -0,0 +1,19 @@ +# $FreeBSD$ +# +# Author: Harti Brandt + +CONTRIB=${.CURDIR}/../../../../contrib/bsnmp/snmp_mibII +.PATH: ${CONTRIB} + +MOD= mibII +SRCS= mibII.c mibII_ifmib.c mibII_ip.c mibII_interfaces.c \ + mibII_ipaddr.c mibII_ifstack.c mibII_rcvaddr.c \ + mibII_nettomedia.c mibII_tcp.c mibII_udp.c mibII_route.c +MAN= snmp_mibII.3 + +DEFS= ${MOD}_tree.def +INCS= snmp_${MOD}.h + +CFLAGS+= -I${INCLUDEDIR}/bsnmp -I${.CURDIR} + +.include diff --git a/lib/libbsnmp/modules/snmp_mibII/genfiles b/lib/libbsnmp/modules/snmp_mibII/genfiles new file mode 100644 index 00000000000..b797670a407 --- /dev/null +++ b/lib/libbsnmp/modules/snmp_mibII/genfiles @@ -0,0 +1,20 @@ +#!/bin/sh +# $FreeBSD$ + +CONTRIB="../../../../contrib/bsnmp/snmp_mibII" + +XSYM="ipAddrTable ifTable ifRcvAddressEntry ifMIB ipMIB tcpMIB udpMIB \ + ipForward ifIndex linkDown linkUp" + +gensnmptree <${CONTRIB}/mibII_tree.def -e ${XSYM} >mibII_oid.h +gensnmptree <${CONTRIB}/mibII_tree.def -l -p mibII_ + +for i in mibII_tree.h mibII_tree.c mibII_oid.h ; do + ex $i <<'EOF' +0a +/* $FreeBSD$ */ +/* generated file, don't edit - use ./genfiles */ +. +wq +EOF +done diff --git a/lib/libbsnmp/modules/snmp_mibII/mibII_oid.h b/lib/libbsnmp/modules/snmp_mibII/mibII_oid.h new file mode 100644 index 00000000000..301f900ef16 --- /dev/null +++ b/lib/libbsnmp/modules/snmp_mibII/mibII_oid.h @@ -0,0 +1,35 @@ +/* $FreeBSD$ */ +/* generated file, don't edit - use ./genfiles */ +#define OID_ipAddrTable 20 +#define OIDLEN_ipAddrTable 8 +#define OIDX_ipAddrTable { 8, { 1, 3, 6, 1, 2, 1, 4, 20, } } +#define OID_ifTable 2 +#define OIDLEN_ifTable 8 +#define OIDX_ifTable { 8, { 1, 3, 6, 1, 2, 1, 2, 2, } } +#define OID_ifRcvAddressEntry 1 +#define OIDLEN_ifRcvAddressEntry 10 +#define OIDX_ifRcvAddressEntry { 10, { 1, 3, 6, 1, 2, 1, 31, 1, 4, 1, } } +#define OID_ifMIB 31 +#define OIDLEN_ifMIB 7 +#define OIDX_ifMIB { 7, { 1, 3, 6, 1, 2, 1, 31, } } +#define OID_ipMIB 48 +#define OIDLEN_ipMIB 7 +#define OIDX_ipMIB { 7, { 1, 3, 6, 1, 2, 1, 48, } } +#define OID_tcpMIB 49 +#define OIDLEN_tcpMIB 7 +#define OIDX_tcpMIB { 7, { 1, 3, 6, 1, 2, 1, 49, } } +#define OID_udpMIB 50 +#define OIDLEN_udpMIB 7 +#define OIDX_udpMIB { 7, { 1, 3, 6, 1, 2, 1, 50, } } +#define OID_ipForward 24 +#define OIDLEN_ipForward 8 +#define OIDX_ipForward { 8, { 1, 3, 6, 1, 2, 1, 4, 24, } } +#define OID_ifIndex 1 +#define OIDLEN_ifIndex 10 +#define OIDX_ifIndex { 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 1, } } +#define OID_linkDown 3 +#define OIDLEN_linkDown 10 +#define OIDX_linkDown { 10, { 1, 3, 6, 1, 6, 3, 1, 1, 5, 3, } } +#define OID_linkUp 4 +#define OIDLEN_linkUp 10 +#define OIDX_linkUp { 10, { 1, 3, 6, 1, 6, 3, 1, 1, 5, 4, } } diff --git a/lib/libbsnmp/modules/snmp_mibII/mibII_tree.c b/lib/libbsnmp/modules/snmp_mibII/mibII_tree.c new file mode 100644 index 00000000000..3d8ecc8e65f --- /dev/null +++ b/lib/libbsnmp/modules/snmp_mibII/mibII_tree.c @@ -0,0 +1,154 @@ +/* $FreeBSD$ */ +/* generated file, don't edit - use ./genfiles */ +#include +#include +#include "asn1.h" +#include "snmp.h" +#include "snmpagent.h" +#include "mibII_tree.h" + +const struct snmp_node mibII_ctree[] = { + {{ 8, { 1, 3, 6, 1, 2, 1, 2, 1, }}, "ifNumber", SNMP_NODE_LEAF, SNMP_SYNTAX_INTEGER, op_interfaces, 0, 0, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 1, }}, "ifIndex", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 2, }}, "ifDescr", SNMP_NODE_COLUMN, SNMP_SYNTAX_OCTETSTRING, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 3, }}, "ifType", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 4, }}, "ifMtu", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 5, }}, "ifSpeed", SNMP_NODE_COLUMN, SNMP_SYNTAX_GAUGE, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 6, }}, "ifPhysAddress", SNMP_NODE_COLUMN, SNMP_SYNTAX_OCTETSTRING, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 7, }}, "ifAdminStatus", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_ifentry, 0|SNMP_NODE_CANSET, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 8, }}, "ifOperStatus", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 9, }}, "ifLastChange", SNMP_NODE_COLUMN, SNMP_SYNTAX_TIMETICKS, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 10, }}, "ifInOctets", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 11, }}, "ifInUcastPkts", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 12, }}, "ifInNUcastPkts", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 13, }}, "ifInDiscards", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 14, }}, "ifInErrors", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 15, }}, "ifInUnknownProtos", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 16, }}, "ifOutOctets", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 17, }}, "ifOutUcastPkts", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 18, }}, "ifOutNUcastPkts", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 19, }}, "ifOutDiscards", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 20, }}, "ifOutErrors", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 21, }}, "ifOutQLen", SNMP_NODE_COLUMN, SNMP_SYNTAX_GAUGE, op_ifentry, 0, 0x11, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 2, 2, 1, 22, }}, "ifSpecific", SNMP_NODE_COLUMN, SNMP_SYNTAX_OID, op_ifentry, 0, 0x11, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 1, }}, "ipForwarding", SNMP_NODE_LEAF, SNMP_SYNTAX_INTEGER, op_ip, 0|SNMP_NODE_CANSET, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 2, }}, "ipDefaultTTL", SNMP_NODE_LEAF, SNMP_SYNTAX_INTEGER, op_ip, 0|SNMP_NODE_CANSET, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 3, }}, "ipInReceives", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ipstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 4, }}, "ipInHdrErrors", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ipstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 5, }}, "ipInAddrErrors", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ipstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 6, }}, "ipForwDatagrams", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ipstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 7, }}, "ipInUnknownProtos", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ipstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 8, }}, "ipInDiscards", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ipstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 9, }}, "ipInDelivers", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ipstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 10, }}, "ipOutRequests", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ipstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 11, }}, "ipOutDiscards", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ipstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 12, }}, "ipOutNoRoutes", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ipstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 13, }}, "ipReasmTimeout", SNMP_NODE_LEAF, SNMP_SYNTAX_INTEGER, op_ipstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 14, }}, "ipReasmReqds", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ipstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 15, }}, "ipReasmOKs", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ipstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 16, }}, "ipReasmFails", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ipstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 17, }}, "ipFragOKs", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ipstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 18, }}, "ipFragFails", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ipstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 4, 19, }}, "ipFragCreates", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ipstat, 0, 0, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 4, 20, 1, 1, }}, "ipAdEntAddr", SNMP_NODE_COLUMN, SNMP_SYNTAX_IPADDRESS, op_ipaddr, 0, 0x41, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 4, 20, 1, 2, }}, "ipAdEntIfIndex", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_ipaddr, 0|SNMP_NODE_CANSET, 0x41, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 4, 20, 1, 3, }}, "ipAdEntNetMask", SNMP_NODE_COLUMN, SNMP_SYNTAX_IPADDRESS, op_ipaddr, 0|SNMP_NODE_CANSET, 0x41, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 4, 20, 1, 4, }}, "ipAdEntBcastAddr", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_ipaddr, 0|SNMP_NODE_CANSET, 0x41, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 4, 20, 1, 5, }}, "ipAdEntReasmMaxSize", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_ipaddr, 0, 0x41, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 4, 22, 1, 1, }}, "ipNetToMediaIfIndex", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_nettomedia, 0, 0x412, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 4, 22, 1, 2, }}, "ipNetToMediaPhysAddress", SNMP_NODE_COLUMN, SNMP_SYNTAX_OCTETSTRING, op_nettomedia, 0, 0x412, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 4, 22, 1, 3, }}, "ipNetToMediaNetAddress", SNMP_NODE_COLUMN, SNMP_SYNTAX_IPADDRESS, op_nettomedia, 0, 0x412, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 4, 22, 1, 4, }}, "ipNetToMediaType", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_nettomedia, 0, 0x412, NULL }, + {{ 9, { 1, 3, 6, 1, 2, 1, 4, 24, 3, }}, "ipCidrRouteNumber", SNMP_NODE_LEAF, SNMP_SYNTAX_GAUGE, op_route, 0, 0, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 4, 24, 4, 1, 1, }}, "ipCidrRouteDest", SNMP_NODE_COLUMN, SNMP_SYNTAX_IPADDRESS, op_route_table, 0, 0x41444, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 4, 24, 4, 1, 2, }}, "ipCidrRouteMask", SNMP_NODE_COLUMN, SNMP_SYNTAX_IPADDRESS, op_route_table, 0, 0x41444, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 4, 24, 4, 1, 3, }}, "ipCidrRouteTos", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_route_table, 0, 0x41444, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 4, 24, 4, 1, 4, }}, "ipCidrRouteNextHop", SNMP_NODE_COLUMN, SNMP_SYNTAX_IPADDRESS, op_route_table, 0, 0x41444, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 4, 24, 4, 1, 5, }}, "ipCidrRouteIfIndex", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_route_table, 0, 0x41444, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 4, 24, 4, 1, 6, }}, "ipCidrRouteType", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_route_table, 0, 0x41444, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 4, 24, 4, 1, 7, }}, "ipCidrRouteProto", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_route_table, 0, 0x41444, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 4, 24, 4, 1, 8, }}, "ipCidrRouteAge", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_route_table, 0, 0x41444, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 4, 24, 4, 1, 9, }}, "ipCidrRouteInfo", SNMP_NODE_COLUMN, SNMP_SYNTAX_OID, op_route_table, 0, 0x41444, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 4, 24, 4, 1, 10, }}, "ipCidrRouteNextHopAS", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_route_table, 0, 0x41444, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 4, 24, 4, 1, 11, }}, "ipCidrRouteMetric1", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_route_table, 0, 0x41444, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 4, 24, 4, 1, 12, }}, "ipCidrRouteMetric2", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_route_table, 0, 0x41444, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 4, 24, 4, 1, 13, }}, "ipCidrRouteMetric3", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_route_table, 0, 0x41444, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 4, 24, 4, 1, 14, }}, "ipCidrRouteMetric4", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_route_table, 0, 0x41444, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 4, 24, 4, 1, 15, }}, "ipCidrRouteMetric5", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_route_table, 0, 0x41444, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 4, 24, 4, 1, 16, }}, "ipCidrRouteStatus", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_route_table, 0, 0x41444, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 1, }}, "icmpInMsgs", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 2, }}, "icmpInErrors", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 3, }}, "icmpInDestUnreachs", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 4, }}, "icmpInTimeExcds", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 5, }}, "icmpInParmProbs", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 6, }}, "icmpInSrcQuenchs", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 7, }}, "icmpInRedirects", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 8, }}, "icmpInEchos", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 9, }}, "icmpInEchoReps", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 10, }}, "icmpInTimestamps", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 11, }}, "icmpInTimestampReps", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 12, }}, "icmpInAddrMasks", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 13, }}, "icmpInAddrMaskReps", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 14, }}, "icmpOutMsgs", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 15, }}, "icmpOutErrors", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 16, }}, "icmpOutDestUnreachs", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 17, }}, "icmpOutTimeExcds", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 18, }}, "icmpOutParmProbs", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 19, }}, "icmpOutSrcQuenchs", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 20, }}, "icmpOutRedirects", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 21, }}, "icmpOutEchos", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 22, }}, "icmpOutEchoReps", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 23, }}, "icmpOutTimestamps", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 24, }}, "icmpOutTimestampReps", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 25, }}, "icmpOutAddrMasks", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 5, 26, }}, "icmpOutAddrMaskReps", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_icmpstat, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 6, 1, }}, "tcpRtoAlgorithm", SNMP_NODE_LEAF, SNMP_SYNTAX_INTEGER, op_tcp, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 6, 2, }}, "tcpRtoMin", SNMP_NODE_LEAF, SNMP_SYNTAX_INTEGER, op_tcp, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 6, 3, }}, "tcpRtoMax", SNMP_NODE_LEAF, SNMP_SYNTAX_INTEGER, op_tcp, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 6, 4, }}, "tcpMaxConn", SNMP_NODE_LEAF, SNMP_SYNTAX_INTEGER, op_tcp, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 6, 5, }}, "tcpActiveOpens", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_tcp, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 6, 6, }}, "tcpPassiveOpens", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_tcp, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 6, 7, }}, "tcpAttemptFails", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_tcp, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 6, 8, }}, "tcpEstabResets", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_tcp, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 6, 9, }}, "tcpCurrEstab", SNMP_NODE_LEAF, SNMP_SYNTAX_GAUGE, op_tcp, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 6, 10, }}, "tcpInSegs", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_tcp, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 6, 11, }}, "tcpOutSegs", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_tcp, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 6, 12, }}, "tcpRetransSegs", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_tcp, 0, 0, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 6, 13, 1, 1, }}, "tcpConnState", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_tcpconn, 0, 0x14144, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 6, 13, 1, 2, }}, "tcpConnLocalAddress", SNMP_NODE_COLUMN, SNMP_SYNTAX_IPADDRESS, op_tcpconn, 0, 0x14144, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 6, 13, 1, 3, }}, "tcpConnLocalPort", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_tcpconn, 0, 0x14144, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 6, 13, 1, 4, }}, "tcpConnRemAddress", SNMP_NODE_COLUMN, SNMP_SYNTAX_IPADDRESS, op_tcpconn, 0, 0x14144, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 6, 13, 1, 5, }}, "tcpConnRemPort", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_tcpconn, 0, 0x14144, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 6, 14, }}, "tcpInErrs", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_tcp, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 7, 1, }}, "udpInDatagrams", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_udp, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 7, 2, }}, "udpNoPorts", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_udp, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 7, 3, }}, "udpInErrors", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_udp, 0, 0, NULL }, + {{ 8, { 1, 3, 6, 1, 2, 1, 7, 4, }}, "udpOutDatagrams", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_udp, 0, 0, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 7, 5, 1, 1, }}, "udpLocalAddress", SNMP_NODE_COLUMN, SNMP_SYNTAX_IPADDRESS, op_udptable, 0, 0x142, NULL }, + {{ 10, { 1, 3, 6, 1, 2, 1, 7, 5, 1, 2, }}, "udpLocalPort", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_udptable, 0, 0x142, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 1, }}, "ifName", SNMP_NODE_COLUMN, SNMP_SYNTAX_OCTETSTRING, op_ifxtable, 0, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 2, }}, "ifInMulticastPkts", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER, op_ifxtable, 0, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 3, }}, "ifInBroadcastPkts", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER, op_ifxtable, 0, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 4, }}, "ifOutMulticastPkts", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER, op_ifxtable, 0, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 5, }}, "ifOutBroadcastPkts", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER, op_ifxtable, 0, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 6, }}, "ifHCInOctets", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER64, op_ifxtable, 0, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 7, }}, "ifHCInUcastPkts", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER64, op_ifxtable, 0, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 8, }}, "ifHCInMulticastPkts", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER64, op_ifxtable, 0, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 9, }}, "ifHCInBroadcastPkts", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER64, op_ifxtable, 0, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 10, }}, "ifHCOutOctets", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER64, op_ifxtable, 0, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 11, }}, "ifHCOutUcastPkts", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER64, op_ifxtable, 0, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 12, }}, "ifHCOutMulticastPkts", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER64, op_ifxtable, 0, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 13, }}, "ifHCOutBroadcastPkts", SNMP_NODE_COLUMN, SNMP_SYNTAX_COUNTER64, op_ifxtable, 0, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 14, }}, "ifLinkUpDownTrapEnable", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_ifxtable, 0|SNMP_NODE_CANSET, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 15, }}, "ifHighSpeed", SNMP_NODE_COLUMN, SNMP_SYNTAX_GAUGE, op_ifxtable, 0, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 16, }}, "ifPromiscuousMode", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_ifxtable, 0|SNMP_NODE_CANSET, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 17, }}, "ifConnectorPresent", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_ifxtable, 0, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 18, }}, "ifAlias", SNMP_NODE_COLUMN, SNMP_SYNTAX_OCTETSTRING, op_ifxtable, 0, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 19, }}, "ifCounterDiscontinuityTime", SNMP_NODE_COLUMN, SNMP_SYNTAX_TIMETICKS, op_ifxtable, 0, 0x11, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 2, 1, 3, }}, "ifStackStatus", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_ifstack, 0, 0x112, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 4, 1, 2, }}, "ifRcvAddressStatus", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_rcvaddr, 0, 0x212, NULL }, + {{ 11, { 1, 3, 6, 1, 2, 1, 31, 1, 4, 1, 3, }}, "ifRcvAddressType", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_rcvaddr, 0, 0x212, NULL }, + {{ 9, { 1, 3, 6, 1, 2, 1, 31, 1, 5, }}, "ifTableLastChange", SNMP_NODE_LEAF, SNMP_SYNTAX_TIMETICKS, op_ifmib, 0, 0, NULL }, + {{ 9, { 1, 3, 6, 1, 2, 1, 31, 1, 6, }}, "ifStackLastChange", SNMP_NODE_LEAF, SNMP_SYNTAX_TIMETICKS, op_ifmib, 0, 0, NULL }, +}; + diff --git a/lib/libbsnmp/modules/snmp_mibII/mibII_tree.h b/lib/libbsnmp/modules/snmp_mibII/mibII_tree.h new file mode 100644 index 00000000000..e19ac3c4d6b --- /dev/null +++ b/lib/libbsnmp/modules/snmp_mibII/mibII_tree.h @@ -0,0 +1,163 @@ +/* $FreeBSD$ */ +/* generated file, don't edit - use ./genfiles */ +int op_interfaces(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_ifNumber 1 +int op_ifentry(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_ifIndex 1 +# define LEAF_ifDescr 2 +# define LEAF_ifType 3 +# define LEAF_ifMtu 4 +# define LEAF_ifSpeed 5 +# define LEAF_ifPhysAddress 6 +# define LEAF_ifAdminStatus 7 +# define LEAF_ifOperStatus 8 +# define LEAF_ifLastChange 9 +# define LEAF_ifInOctets 10 +# define LEAF_ifInUcastPkts 11 +# define LEAF_ifInNUcastPkts 12 +# define LEAF_ifInDiscards 13 +# define LEAF_ifInErrors 14 +# define LEAF_ifInUnknownProtos 15 +# define LEAF_ifOutOctets 16 +# define LEAF_ifOutUcastPkts 17 +# define LEAF_ifOutNUcastPkts 18 +# define LEAF_ifOutDiscards 19 +# define LEAF_ifOutErrors 20 +# define LEAF_ifOutQLen 21 +# define LEAF_ifSpecific 22 +int op_ip(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_ipForwarding 1 +# define LEAF_ipDefaultTTL 2 +int op_ipstat(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_ipInReceives 3 +# define LEAF_ipInHdrErrors 4 +# define LEAF_ipInAddrErrors 5 +# define LEAF_ipForwDatagrams 6 +# define LEAF_ipInUnknownProtos 7 +# define LEAF_ipInDiscards 8 +# define LEAF_ipInDelivers 9 +# define LEAF_ipOutRequests 10 +# define LEAF_ipOutDiscards 11 +# define LEAF_ipOutNoRoutes 12 +# define LEAF_ipReasmTimeout 13 +# define LEAF_ipReasmReqds 14 +# define LEAF_ipReasmOKs 15 +# define LEAF_ipReasmFails 16 +# define LEAF_ipFragOKs 17 +# define LEAF_ipFragFails 18 +# define LEAF_ipFragCreates 19 +int op_ipaddr(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_ipAdEntAddr 1 +# define LEAF_ipAdEntIfIndex 2 +# define LEAF_ipAdEntNetMask 3 +# define LEAF_ipAdEntBcastAddr 4 +# define LEAF_ipAdEntReasmMaxSize 5 +int op_nettomedia(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_ipNetToMediaIfIndex 1 +# define LEAF_ipNetToMediaPhysAddress 2 +# define LEAF_ipNetToMediaNetAddress 3 +# define LEAF_ipNetToMediaType 4 +int op_route(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_ipCidrRouteNumber 3 +int op_route_table(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_ipCidrRouteDest 1 +# define LEAF_ipCidrRouteMask 2 +# define LEAF_ipCidrRouteTos 3 +# define LEAF_ipCidrRouteNextHop 4 +# define LEAF_ipCidrRouteIfIndex 5 +# define LEAF_ipCidrRouteType 6 +# define LEAF_ipCidrRouteProto 7 +# define LEAF_ipCidrRouteAge 8 +# define LEAF_ipCidrRouteInfo 9 +# define LEAF_ipCidrRouteNextHopAS 10 +# define LEAF_ipCidrRouteMetric1 11 +# define LEAF_ipCidrRouteMetric2 12 +# define LEAF_ipCidrRouteMetric3 13 +# define LEAF_ipCidrRouteMetric4 14 +# define LEAF_ipCidrRouteMetric5 15 +# define LEAF_ipCidrRouteStatus 16 +int op_icmpstat(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_icmpInMsgs 1 +# define LEAF_icmpInErrors 2 +# define LEAF_icmpInDestUnreachs 3 +# define LEAF_icmpInTimeExcds 4 +# define LEAF_icmpInParmProbs 5 +# define LEAF_icmpInSrcQuenchs 6 +# define LEAF_icmpInRedirects 7 +# define LEAF_icmpInEchos 8 +# define LEAF_icmpInEchoReps 9 +# define LEAF_icmpInTimestamps 10 +# define LEAF_icmpInTimestampReps 11 +# define LEAF_icmpInAddrMasks 12 +# define LEAF_icmpInAddrMaskReps 13 +# define LEAF_icmpOutMsgs 14 +# define LEAF_icmpOutErrors 15 +# define LEAF_icmpOutDestUnreachs 16 +# define LEAF_icmpOutTimeExcds 17 +# define LEAF_icmpOutParmProbs 18 +# define LEAF_icmpOutSrcQuenchs 19 +# define LEAF_icmpOutRedirects 20 +# define LEAF_icmpOutEchos 21 +# define LEAF_icmpOutEchoReps 22 +# define LEAF_icmpOutTimestamps 23 +# define LEAF_icmpOutTimestampReps 24 +# define LEAF_icmpOutAddrMasks 25 +# define LEAF_icmpOutAddrMaskReps 26 +int op_tcp(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_tcpRtoAlgorithm 1 +# define LEAF_tcpRtoMin 2 +# define LEAF_tcpRtoMax 3 +# define LEAF_tcpMaxConn 4 +# define LEAF_tcpActiveOpens 5 +# define LEAF_tcpPassiveOpens 6 +# define LEAF_tcpAttemptFails 7 +# define LEAF_tcpEstabResets 8 +# define LEAF_tcpCurrEstab 9 +# define LEAF_tcpInSegs 10 +# define LEAF_tcpOutSegs 11 +# define LEAF_tcpRetransSegs 12 +int op_tcpconn(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_tcpConnState 1 +# define LEAF_tcpConnLocalAddress 2 +# define LEAF_tcpConnLocalPort 3 +# define LEAF_tcpConnRemAddress 4 +# define LEAF_tcpConnRemPort 5 +# define LEAF_tcpInErrs 14 +int op_udp(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_udpInDatagrams 1 +# define LEAF_udpNoPorts 2 +# define LEAF_udpInErrors 3 +# define LEAF_udpOutDatagrams 4 +int op_udptable(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_udpLocalAddress 1 +# define LEAF_udpLocalPort 2 +int op_ifxtable(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_ifName 1 +# define LEAF_ifInMulticastPkts 2 +# define LEAF_ifInBroadcastPkts 3 +# define LEAF_ifOutMulticastPkts 4 +# define LEAF_ifOutBroadcastPkts 5 +# define LEAF_ifHCInOctets 6 +# define LEAF_ifHCInUcastPkts 7 +# define LEAF_ifHCInMulticastPkts 8 +# define LEAF_ifHCInBroadcastPkts 9 +# define LEAF_ifHCOutOctets 10 +# define LEAF_ifHCOutUcastPkts 11 +# define LEAF_ifHCOutMulticastPkts 12 +# define LEAF_ifHCOutBroadcastPkts 13 +# define LEAF_ifLinkUpDownTrapEnable 14 +# define LEAF_ifHighSpeed 15 +# define LEAF_ifPromiscuousMode 16 +# define LEAF_ifConnectorPresent 17 +# define LEAF_ifAlias 18 +# define LEAF_ifCounterDiscontinuityTime 19 +int op_ifstack(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_ifStackStatus 3 +int op_rcvaddr(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_ifRcvAddressStatus 2 +# define LEAF_ifRcvAddressType 3 +int op_ifmib(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_ifTableLastChange 5 +# define LEAF_ifStackLastChange 6 +#define mibII_CTREE_SIZE 142 +extern const struct snmp_node mibII_ctree[]; diff --git a/lib/libbsnmp/modules/snmp_netgraph/BEGEMOT-NETGRAPH.txt b/lib/libbsnmp/modules/snmp_netgraph/BEGEMOT-NETGRAPH.txt new file mode 100644 index 00000000000..d49216a1a41 --- /dev/null +++ b/lib/libbsnmp/modules/snmp_netgraph/BEGEMOT-NETGRAPH.txt @@ -0,0 +1,398 @@ +-- +-- Copyright (c) 2001-2003 +-- Fraunhofer Institute for Open Communication Systems (FhG Fokus). +-- All rights reserved. +-- +-- Author: Harti Brandt +-- +-- 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. +-- +-- 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. +-- +-- $FreeBSD$ +-- +-- Private MIB for netgraph part of Begemot SNMP daemon. +-- +BEGEMOT-NETGRAPH-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, Counter32, Unsigned32 + FROM SNMPv2-SMI + TEXTUAL-CONVENTION, TruthValue + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP + FROM SNMPv2-CONF + begemot + FROM BEGEMOT-MIB; + +begemotNg MODULE-IDENTITY + LAST-UPDATED "200201310000Z" + 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 for the NetGraph access module for SNMP." + ::= { begemot 2 } + +begemotNgObjects OBJECT IDENTIFIER ::= { begemotNg 1 } + +-- -------------------------------------------------------------------------- + +NgTypeName ::= TEXTUAL-CONVENTION + DISPLAY-HINT "15a" + STATUS current + DESCRIPTION + "Name of a netgraph type." + SYNTAX OCTET STRING (SIZE(1..15)) + +NgNodeName ::= TEXTUAL-CONVENTION + DISPLAY-HINT "15a" + STATUS current + DESCRIPTION + "Name of a netgraph node." + SYNTAX OCTET STRING (SIZE(1..15)) + +NgNodeNameOrEmpty ::= TEXTUAL-CONVENTION + DISPLAY-HINT "15a" + STATUS current + DESCRIPTION + "Name of a netgraph node." + SYNTAX OCTET STRING (SIZE(0..15)) + +NgHookName ::= TEXTUAL-CONVENTION + DISPLAY-HINT "15a" + STATUS current + DESCRIPTION + "Name of a netgraph hook." + SYNTAX OCTET STRING (SIZE(1..15)) + +NgNodeId ::= TEXTUAL-CONVENTION + DISPLAY-HINT "x" + STATUS current + DESCRIPTION + "Node identifier." + SYNTAX Unsigned32 (1..4294967295) + +NgNodeIdOrZero ::= TEXTUAL-CONVENTION + DISPLAY-HINT "x" + STATUS current + DESCRIPTION + "Node identifier or 0 for 'no-node'." + SYNTAX Unsigned32 (0..4294967295) + +-- -------------------------------------------------------------------------- +-- +-- Configuration parameters +-- +begemotNgConfig OBJECT IDENTIFIER ::= { begemotNgObjects 1 } + +begemotNgControlNodeName OBJECT-TYPE + SYNTAX NgNodeName + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The name of the netgraph node of this daemon. The name is + writeable during initialisation. If the name is set from + the empty string to the non-empty string, the netgraph socket + is created. Once set it cannot be changed." + ::= { begemotNgConfig 1 } + +begemotNgResBufSiz OBJECT-TYPE + SYNTAX INTEGER (1024..65536) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The size of the receive buffers for netgraph messages." + DEFVAL { 20000 } + ::= { begemotNgConfig 2 } + +begemotNgTimeout OBJECT-TYPE + SYNTAX INTEGER (10..10000) + UNITS "milliseconds" + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The maximum time to wait for a response to a netgraph message." + DEFVAL { 1000 } + ::= { begemotNgConfig 3 } + +begemotNgDebugLevel OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The netgraph library debug level. This should be set only + if the daemon is run with a terminal attached." + DEFVAL { 0 } + ::= { begemotNgConfig 4 } + +-- -------------------------------------------------------------------------- +-- +-- The STATISTICS Group +-- +begemotNgStats OBJECT IDENTIFIER ::= { begemotNgObjects 2 } + +begemotNgNoMems OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of times a memory allocation has failed for buffers + or the message queue." + ::= { begemotNgStats 1 } + +begemotNgMsgReadErrs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of times reading a netgraph message has failed." + ::= { begemotNgStats 2 } + +begemotNgTooLargeMsgs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of times a netgraph message was too large for + the buffer. Try increasing begemotNgResBufSiz if + this happens." + ::= { begemotNgStats 3 } + +begemotNgDataReadErrs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of times reading a netgraph data message has failed." + ::= { begemotNgStats 4 } + +begemotNgTooLargeDatas OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of times a netgraph data message was too large. + You need to increase begemotNgResBufSiz." + ::= { begemotNgStats 5 } + +-- ----------------------------------------------------- +-- +-- The NODE table +-- +begemotNgTypeTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotNgTypeEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table containing information about all netgraph node types." + ::= { begemotNgObjects 3 } + +begemotNgTypeEntry OBJECT-TYPE + SYNTAX BegemotNgTypeEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Table entry that describes one netgraph node." + INDEX { begemotNgTypeName } + ::= { begemotNgTypeTable 1 } + +BegemotNgTypeEntry ::= SEQUENCE { + begemotNgTypeName NgTypeName, + begemotNgTypeStatus INTEGER +} + +begemotNgTypeName OBJECT-TYPE + SYNTAX NgTypeName + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The name of the type. Used as index." + ::= { begemotNgTypeEntry 1 } + +begemotNgTypeStatus OBJECT-TYPE + SYNTAX INTEGER { loaded(1), unloaded(2) } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "If loaded then the node type is available. A type can be load + by setting this field to loaded. It is unload if the field is + set to unloaded. Note, that a type cannot be unloaded if it + is compiled into the kernel or has nodes of this type. The name + of the file containing the type implementation is constructed by + prepending ng_ to the type name." + ::= { begemotNgTypeEntry 2 } + +-- +-- Node table +-- +begemotNgNodeTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotNgNodeEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table containing information about all netgraph nodes." + ::= { begemotNgObjects 4 } + +begemotNgNodeEntry OBJECT-TYPE + SYNTAX BegemotNgNodeEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Table entry that describes one netgraph node." + INDEX { begemotNgNodeId } + ::= { begemotNgNodeTable 1 } + +BegemotNgNodeEntry ::= SEQUENCE { + begemotNgNodeId NgNodeId, + begemotNgNodeStatus INTEGER, + begemotNgNodeName NgNodeNameOrEmpty, + begemotNgNodeType NgTypeName, + begemotNgNodeHooks Unsigned32 +} + +begemotNgNodeId OBJECT-TYPE + SYNTAX NgNodeId + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The 32bit node id of this node. 0 is an illegal value." + ::= { begemotNgNodeEntry 1 } + +begemotNgNodeStatus OBJECT-TYPE + SYNTAX INTEGER { valid(1), invalid(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Indicates whether the node exists or not." + ::= { begemotNgNodeEntry 2 } + +begemotNgNodeName OBJECT-TYPE + SYNTAX NgNodeNameOrEmpty + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Name of the node (if any)." + ::= { begemotNgNodeEntry 3 } + +begemotNgNodeType OBJECT-TYPE + SYNTAX NgTypeName + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Type name of the node." + ::= { begemotNgNodeEntry 4 } + +begemotNgNodeHooks OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of hooks on this node." + ::= { begemotNgNodeEntry 5 } + +-- +-- Hook table +-- +begemotNgHookTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotNgHookEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table containing information about all netgraph hooks." + ::= { begemotNgObjects 5 } + +begemotNgHookEntry OBJECT-TYPE + SYNTAX BegemotNgHookEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Table entry that describes one netgraph node." + INDEX { begemotNgHookNodeId, begemotNgHookHook } + ::= { begemotNgHookTable 1 } + +BegemotNgHookEntry ::= SEQUENCE { + begemotNgHookNodeId NgNodeId, + begemotNgHookHook NgHookName, + begemotNgHookStatus INTEGER, + begemotNgHookPeerNodeId NgNodeId, + begemotNgHookPeerHook NgHookName, + begemotNgHookPeerType NgTypeName +} + +begemotNgHookNodeId OBJECT-TYPE + SYNTAX NgNodeId + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The 32bit node id of this node." + ::= { begemotNgHookEntry 1 } + +begemotNgHookHook OBJECT-TYPE + SYNTAX NgHookName + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Name of the hook." + ::= { begemotNgHookEntry 2 } + +begemotNgHookStatus OBJECT-TYPE + SYNTAX INTEGER { valid(1), invalid(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Indicates whether the hook exists or not." + ::= { begemotNgHookEntry 3 } + +begemotNgHookPeerNodeId OBJECT-TYPE + SYNTAX NgNodeId + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The 32bit node id of the peer node of this hook." + ::= { begemotNgHookEntry 4 } + +begemotNgHookPeerHook OBJECT-TYPE + SYNTAX NgHookName + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Name of the peer hook." + ::= { begemotNgHookEntry 5 } + +begemotNgHookPeerType OBJECT-TYPE + SYNTAX NgTypeName + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Name of the peer type." + ::= { begemotNgHookEntry 6 } + +END diff --git a/lib/libbsnmp/modules/snmp_netgraph/Makefile b/lib/libbsnmp/modules/snmp_netgraph/Makefile new file mode 100644 index 00000000000..6ccdf5f40f6 --- /dev/null +++ b/lib/libbsnmp/modules/snmp_netgraph/Makefile @@ -0,0 +1,15 @@ +# $FreeBSD$ +# +# Author: Harti Brandt + +MOD= netgraph +SRCS= snmp_netgraph.c +MAN= snmp_netgraph.3 + +MIBS= BEGEMOT-NETGRAPH.txt +DEFS= ${MOD}_tree.def +INCS= snmp_${MOD}.h + +CFLAGS+= -I${INCLUDEDIR}/bsnmp -I${.CURDIR} + +.include diff --git a/lib/libbsnmp/modules/snmp_netgraph/genfiles b/lib/libbsnmp/modules/snmp_netgraph/genfiles new file mode 100644 index 00000000000..b92a39228ea --- /dev/null +++ b/lib/libbsnmp/modules/snmp_netgraph/genfiles @@ -0,0 +1,17 @@ +#!/bin/sh +# $FreeBSD$ + +XSYM="begemotNg" + +gensnmptree netgraph_oid.h +gensnmptree +#include +#include "asn1.h" +#include "snmp.h" +#include "snmpagent.h" +#include "netgraph_tree.h" + +const struct snmp_node netgraph_ctree[] = { + {{ 12, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 1, 1, }}, "begemotNgControlNodeName", SNMP_NODE_LEAF, SNMP_SYNTAX_OCTETSTRING, op_ng_config, 0|SNMP_NODE_CANSET, 0, NULL }, + {{ 12, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 1, 2, }}, "begemotNgResBufSiz", SNMP_NODE_LEAF, SNMP_SYNTAX_INTEGER, op_ng_config, 0|SNMP_NODE_CANSET, 0, NULL }, + {{ 12, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 1, 3, }}, "begemotNgTimeout", SNMP_NODE_LEAF, SNMP_SYNTAX_INTEGER, op_ng_config, 0|SNMP_NODE_CANSET, 0, NULL }, + {{ 12, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 1, 4, }}, "begemotNgDebugLevel", SNMP_NODE_LEAF, SNMP_SYNTAX_GAUGE, op_ng_config, 0|SNMP_NODE_CANSET, 0, NULL }, + {{ 12, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 2, 1, }}, "begemotNgNoMems", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ng_stats, 0, 0, NULL }, + {{ 12, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 2, 2, }}, "begemotNgMsgReadErrs", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ng_stats, 0, 0, NULL }, + {{ 12, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 2, 3, }}, "begemotNgTooLargeMsgs", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ng_stats, 0, 0, NULL }, + {{ 12, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 2, 4, }}, "begemotNgDataReadErrs", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ng_stats, 0, 0, NULL }, + {{ 12, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 2, 5, }}, "begemotNgTooLargeDatas", SNMP_NODE_LEAF, SNMP_SYNTAX_COUNTER, op_ng_stats, 0, 0, NULL }, + {{ 13, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 3, 1, 2, }}, "begemotNgTypeStatus", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_ng_type, 0|SNMP_NODE_CANSET, 0x21, NULL }, + {{ 13, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 4, 1, 2, }}, "begemotNgNodeStatus", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_ng_node, 0, 0x11, NULL }, + {{ 13, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 4, 1, 3, }}, "begemotNgNodeName", SNMP_NODE_COLUMN, SNMP_SYNTAX_OCTETSTRING, op_ng_node, 0, 0x11, NULL }, + {{ 13, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 4, 1, 4, }}, "begemotNgNodeType", SNMP_NODE_COLUMN, SNMP_SYNTAX_OCTETSTRING, op_ng_node, 0, 0x11, NULL }, + {{ 13, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 4, 1, 5, }}, "begemotNgNodeHooks", SNMP_NODE_COLUMN, SNMP_SYNTAX_GAUGE, op_ng_node, 0, 0x11, NULL }, + {{ 13, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 5, 1, 3, }}, "begemotNgHookStatus", SNMP_NODE_COLUMN, SNMP_SYNTAX_INTEGER, op_ng_hook, 0, 0x262, NULL }, + {{ 13, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 5, 1, 4, }}, "begemotNgHookPeerNodeId", SNMP_NODE_COLUMN, SNMP_SYNTAX_GAUGE, op_ng_hook, 0, 0x262, NULL }, + {{ 13, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 5, 1, 5, }}, "begemotNgHookPeerHook", SNMP_NODE_COLUMN, SNMP_SYNTAX_OCTETSTRING, op_ng_hook, 0, 0x262, NULL }, + {{ 13, { 1, 3, 6, 1, 4, 1, 12325, 1, 2, 1, 5, 1, 6, }}, "begemotNgHookPeerType", SNMP_NODE_COLUMN, SNMP_SYNTAX_OCTETSTRING, op_ng_hook, 0, 0x262, NULL }, +}; + diff --git a/lib/libbsnmp/modules/snmp_netgraph/netgraph_tree.def b/lib/libbsnmp/modules/snmp_netgraph/netgraph_tree.def new file mode 100644 index 00000000000..eff59ff15c7 --- /dev/null +++ b/lib/libbsnmp/modules/snmp_netgraph/netgraph_tree.def @@ -0,0 +1,78 @@ +# +# Copyright (c) 2001-2003 +# Fraunhofer Institute for Open Communication Systems (FhG Fokus). +# All rights reserved. +# +# Author: Harti Brandt +# +# 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. +# +# 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. +# +# $FreeBSD$ +# +# Definition of the tree implemented by snmp_netgraph. +# +(1 internet + (4 private + (1 enterprises + (12325 fokus + (1 begemot + (2 begemotNg + (1 begemotNgObjects + (1 begemotNgConfig + (1 begemotNgControlNodeName OCTETSTRING op_ng_config GET SET) + (2 begemotNgResBufSiz INTEGER op_ng_config GET SET) + (3 begemotNgTimeout INTEGER op_ng_config GET SET) + (4 begemotNgDebugLevel UNSIGNED32 op_ng_config GET SET) + ) +# Change definition of stats array if you change StatsGroup + (2 begemotNgStats + (1 begemotNgNoMems COUNTER op_ng_stats GET) + (2 begemotNgMsgReadErrs COUNTER op_ng_stats GET) + (3 begemotNgTooLargeMsgs COUNTER op_ng_stats GET) + (4 begemotNgDataReadErrs COUNTER op_ng_stats GET) + (5 begemotNgTooLargeDatas COUNTER op_ng_stats GET) + ) + (3 begemotNgTypeTable + (1 begemotNgTypeEntry : OCTETSTRING op_ng_type + (1 begemotNgTypeName OCTETSTRING) + (2 begemotNgTypeStatus INTEGER GET SET) + )) + (4 begemotNgNodeTable + (1 begemotNgNodeEntry : INTEGER op_ng_node + (1 begemotNgNodeId UNSIGNED32) + (2 begemotNgNodeStatus INTEGER GET) + (3 begemotNgNodeName OCTETSTRING GET) + (4 begemotNgNodeType OCTETSTRING GET) + (5 begemotNgNodeHooks UNSIGNED32 GET) + )) + (5 begemotNgHookTable + (1 begemotNgHookEntry : UNSIGNED32 OCTETSTRING op_ng_hook + (1 begemotNgHookNodeId UNSIGNED32) + (2 begemotNgHookHook OCTETSTRING) + (3 begemotNgHookStatus INTEGER GET) + (4 begemotNgHookPeerNodeId UNSIGNED32 GET) + (5 begemotNgHookPeerHook OCTETSTRING GET) + (6 begemotNgHookPeerType OCTETSTRING GET) + )) + )) +))))) diff --git a/lib/libbsnmp/modules/snmp_netgraph/netgraph_tree.h b/lib/libbsnmp/modules/snmp_netgraph/netgraph_tree.h new file mode 100644 index 00000000000..5b6d3f6d1c7 --- /dev/null +++ b/lib/libbsnmp/modules/snmp_netgraph/netgraph_tree.h @@ -0,0 +1,27 @@ +/* $FreeBSD$ */ +/* generated file, don't edit - use ./genfiles */ +int op_ng_config(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_begemotNgControlNodeName 1 +# define LEAF_begemotNgResBufSiz 2 +# define LEAF_begemotNgTimeout 3 +# define LEAF_begemotNgDebugLevel 4 +int op_ng_stats(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_begemotNgNoMems 1 +# define LEAF_begemotNgMsgReadErrs 2 +# define LEAF_begemotNgTooLargeMsgs 3 +# define LEAF_begemotNgDataReadErrs 4 +# define LEAF_begemotNgTooLargeDatas 5 +int op_ng_type(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_begemotNgTypeStatus 2 +int op_ng_node(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_begemotNgNodeStatus 2 +# define LEAF_begemotNgNodeName 3 +# define LEAF_begemotNgNodeType 4 +# define LEAF_begemotNgNodeHooks 5 +int op_ng_hook(struct snmp_context *, struct snmp_value *, u_int, u_int, enum snmp_op); +# define LEAF_begemotNgHookStatus 3 +# define LEAF_begemotNgHookPeerNodeId 4 +# define LEAF_begemotNgHookPeerHook 5 +# define LEAF_begemotNgHookPeerType 6 +#define netgraph_CTREE_SIZE 18 +extern const struct snmp_node netgraph_ctree[]; diff --git a/lib/libbsnmp/modules/snmp_netgraph/snmp_netgraph.3 b/lib/libbsnmp/modules/snmp_netgraph/snmp_netgraph.3 new file mode 100644 index 00000000000..fdd55faf1fe --- /dev/null +++ b/lib/libbsnmp/modules/snmp_netgraph/snmp_netgraph.3 @@ -0,0 +1,416 @@ +.\" +.\" Copyright (c) 2001-2003 +.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus). +.\" All rights reserved. +.\" +.\" Author: Harti Brandt +.\" +.\" 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. +.\" +.\" 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. +.\" +.\" $FreeBSD$ +.\" +.Dd October 7, 2003 +.Dt snmp_netgraph 3 +.Os +.Sh NAME +.Nm snmp_node , +.Nm snmp_nodename , +.Nm ng_cookie_f , +.Nm ng_hook_f , +.Nm ng_register_cookie , +.Nm ng_unregister_cookie , +.Nm ng_register_hook , +.Nm ng_unregister_hook , +.Nm ng_unregister_module , +.Nm ng_output , +.Nm ng_output_node , +.Nm ng_output_id , +.Nm ng_dialog , +.Nm ng_dialog_node , +.Nm ng_dialog_id , +.Nm ng_send_data , +.Nm ng_mkpeer_id , +.Nm ng_connect_node , +.Nm ng_connect_id , +.Nm ng_connect2_id , +.Nm ng_connect2_tee_id , +.Nm ng_rmhook , +.Nm ng_rmhook_id , +.Nm ng_rmhook_tee_id , +.Nm ng_shutdown_id , +.Nm ng_next_node_id , +.Nm ng_node_id , +.Nm ng_node_id_node , +.Nm ng_node_name , +.Nm ng_node_type , +.Nm ng_peer_hook_id +.Nd "netgraph module for snmpd. +.Sh LIBRARY +.Pq begemotSnmpdModulePath."netgraph" = "/usr/lib/snmp_netgraph.so" +.Sh SYNOPSIS +.In bsnmp/snmpmod.h +.In bsnmp/snmp_netgraph.h +.Vt extern ng_ID_t snmp_node ; +.Vt extern u_char *snmp_nodename ; +.Ft typedef void +.Fn ng_cookie_f "const struct ng_mesg *mesg" "const char *path" "ng_ID_t id" "void *uarg" +.Ft typedef void +.Fn ng_hook_f "const char *hook" "const u_char *mesg" "size_t len" "void *uarg" +.Ft void * +.Fn ng_register_cookie "const struct lmodule *mod" "u_int32_t cookie" "ng_ID_t id" "ng_cookie_f *func" "void *uarg" +.Ft void +.Fn ng_unregister_cookie "void *reg" +.Ft void * +.Fn ng_register_hook "const struct lmodule *mod" "const char *hook" "ng_hook_f *func" "void *uarg" +.Ft void +.Fn ng_unregister_hook "void *reg" +.Ft void +.Fn ng_unregister_module "const struct lmodule *mod" +.Ft int +.Fn ng_output "const char *path" "u_int cookie" "u_int opcode" "const void *arg" "size_t arglen" +.Ft int +.Fn ng_output_node "const char *node" "u_int cookie" "u_int opcode" "const void *arg" "size_t arglen" " +.Ft int +.Fn ng_output_id "ng_ID_t node" "u_int cookie" "u_int opcode" "const void *arg" "size_t arglen" " +.Ft struct ng_mesg * +.Fn ng_dialog "const char *path" "u_int cookie" "u_int opcode" "const void *arg" "size_t arglen" +.Ft struct ng_mesg * +.Fn ng_dialog_node "const char *node" "u_int cookie" "u_int opcode" "const void *arg" "size_t arglen" " +.Ft struct ng_mesg * +.Fn ng_dialog_id "ng_ID_t id" "u_int cookie" "u_int opcode" "const void *arg" "size_t arglen" " +.Ft int +.Fn ng_send_data "const char *hook" "const void *sndbuf" "size_t sndlen" +.Ft ng_ID_t +.Fn ng_mkpeer_id "ng_ID_t id" "const char *name" "const char *type" "const char *hook" "const char *peerhook" +.Ft int +.Fn ng_connect_node "const char *node" "const char *ourhook" "const char *peerhook" +.Ft int +.Fn ng_connect_id "ng_ID_t id" "const char *ourhook" "const char *peerhook" +.Ft int +.Fn ng_connect2_id "ng_ID_t id" "ng_ID_t peer" "const char *ourhook" "const char *peerhook" +.Ft int +.Fn ng_connect2_tee_id "ng_ID_t id" "ng_ID_t peer" "const char *ourhook" "const char *peerhook" +.Ft int +.Fn ng_rmhook "const char *ourhook" +.Ft int +.Fn ng_rmhook_id "ng_ID_t id" "const char *hook" +.Ft int +.Fn ng_rmhook_tee_id "ng_ID_t id" "const char *hook" +.Ft int +.Fn ng_shutdown_id "ng_ID_t id" +.Ft ng_ID_t +.Fn ng_next_node_id "ng_ID_t node, const char *type, const char *hook); +.Ft ng_ID_t +.Fn ng_node_id "const char *path" +.Ft ng_ID_t +.Fn ng_node_id_node "const char *node" +.Ft ng_ID_t +.Fn ng_node_name "ng_ID_t id, char *name" +.Ft ng_ID_t +.Fn ng_node_type "ng_ID_t id, char *type" +.Ft int +.Fn ng_peer_hook_id "ng_ID_t id" "const char *hook" "char *peerhook" +.Sh DESCRIPTION +The +.Nm snmp_netgraph +module implements a number of tables and scalars that enable remote access to +the netgraph subsystem. It also exports a number of global variables and +functions, that allow other modules to easily use the netgraph system. +.Pp +If upon start up of the module the variable +.Va begemotNgControlNodeName +is not empty the module opens a netgraph socket and names that socket node. +If the variable is empty, the socket is created, as soon as the variable is +written with a non-empty name. The socket can be closed by writing an empty +string to the variable. The socket itself and its name are available in +.Va snmp_node +and +.Va snmp_nodename . +.Ss SENDING AND RECEIVING MESSAGES AND DATA +There are three functions for sending control message: +.Bl -tag -width ".It Fn ng_output_node" +.It Fn ng_output +sends a control message along the given +.Fa path . +.It Fn ng_output_node +sends a control message to the node with name +.Fa node +and +.It Fn ng_output_id +sends a control message to the node with node id +.Fa id . +.El +.Pp +Each of these functions takes the following arguments: +.Bl -tag -width ".It Fa cookie" +.It Fa cookie +is the node specific command cookie, +.It Fa opcode +is the node specific code for the operation to performa, +.It Fa arg +is a pointer to the message itself. This message must start with a +.Vt struct ng_mesg . +.It Fa arglen +is the overall length of the message (header plus arguments). +.El +The functions return the message id that can be used to match incoming responses +or -1 if an error occurs. +.Pp +Another class of functions is used to send a control message and to wait for +a matching response. Note, that this operation blocks the daemon, so use it +only if you are sure that the response will happen. There is a maximum timeout +that is configurable in the MIB variable +.Va begemotNgTimeout . +Other messages arriving while the functions are waiting for the response are +queued and delivered on the next call to the module's idle function. +.Bl -tag -width ".It Fn ng_output_node" +.It Fn ng_dialog +sends a control message along the given +.Fa path +and waits for a matching response. +.It Fn ng_dialog_node +sends a control message to the node with name +.Fa node +and waits for a matching response. +.It Fn ng_dialog_id +sends a control message to the node with id +.Fa id +and waits for a matching response. +.El +.Pp +All three functions take the same arguments as the +.Fn ng_output* +functions. The functions return the reponse message in a buffer allocated by +.Xr malloc 3 +or NULL in case of an error. The maximum size of the response buffer can be +configured in the variable +.Va begemotNgResBufSiz . +.Pp +A data message can be send with the function +.Fn ng_send_data . +This function takes the name of the +.Va snmp_node Ns 's +hook through which to send the data, a pointer to the message buffer and +the size of the message. It returns -1 if an error happens. +.Ss ASYNCHRONOUS CONTROL AND DATA MESSAGES +A module can register functions to asynchronuosly receive control and data +message. +.Pp +The function +.Fn ng_register_cookie +registers a control message receive function. If a control message is +received, that is not consumed by the dialog functions, the list of registerred +control message receive functions is scanned. If the cookie in the received +message is the same as the +.Fa cookie +argument to the +.Fn ng_register_cookie +call and the +.Fn +.Fa id +argument to the +.Fn ng_register_cookie +call was either 0 or equals the node id which sent the control message, the +handler function +.Fa func +is called with a pointer to the received message, the hook on which the +message was received (or NULL if it was received not on a hook), the id +of the sender's node and the +.Fa uarg +argument of the registration call. The handler function should not modify +the contents of the message, because more than one function may be registered +to the same cookie and node id. +.Pp +A control message registration can be undone by calling +.Fn ng_unregister_cookie +with the return value of the registration call. +If an error occures while registering, +.Fn ng_register_cookie +returns NULL. +.Pp +A module can call +.Fn ng_register_hook +to register a callback for data messages on one of the +.Va snmp_node Ns 's +hooks. If a data message is received on that hook, the callback function +.Fa func +is called with the hook name, a pointer to the data message, the size of +the message and the argument +.Fa uarg +to the registration function. The message should be treated as read-only. +A data message registration can be undone by calling +.Fn ng_unregister_hook +with the return value of the registration call. +If an error occures while registering, +.Fn ng_register_hook +returns NULL. +.Pp +The function +.Fn ng_unregister_module +removes all control and data registrations for that module. +.Ss FINDING NODES AND NODE CHARACTERISTICS +.Pp +The function +.Fn ng_node_id +returns the id of the node addressed by +.Fa path +or 0 if the node does not exists. +.Pp +The function +.Fn ng_node_id_node +returns the id of the node with name +.Fa node +or 0 if the node does not exist. +.Pp +The function +.Fn ng_node_node +retrieves the name of the node with id +.Fa id +and writes it to the buffer pointed to by +.Fa name . +This buffer should be at least +.Li NG_NODELEN ++ 1 long. The function returns the node id or 0 if the +node is not found +.Pp +The function +.Fn ng_node_type +retrieves the name of the node with id +.Fa id +and writes it to the buffer pointed to by +.Fa type . +This buffer should be at least +.Li NG_TYPELEN ++ 1 long. The function returns the node id or 0 if the +node is not found. +.Pp +The function +.Fn ng_peer_hook_id +writes the name of the peer hook of the hook +.Fa hook +on the node with +.Fa id +to the buffer pointed to by +.Fa peer_hook . +The buffer should be at least +.Li NG_HOOKLEN ++ 1 long. The function returns 0 if the node and the hook is found, -1 +otherwise. The function skips intermediate tee nodes (see +.Xr ng_tee 4 ). +.Pp +The function +.Fn ng_next_node_id +returns the node id of the peer node that is on the other side of hook +.Fa hook +of node +.Fa id . +If +.Fa type +is not NULL, the function checks, that the peer node's type is +.Fa type . +The function skips intermediate tee nodes (see +.Xr ng_tee 4 ). +It returns the node id of the peer node or 0 if an error occurres or the +types do not match. +.Ss CHANGING THE GRAPH +A number of functions can be used to create or destroy nodes and hooks. +.Pp +The function +.Fn ng_mkpeer_id +creates a new node of type +.Fa type +who's hook +.Fa peerhook +will be connected to +.Fa hook +of node +.Fa id . +If +.Fa name +is not NULL the new node is named with this name. The function returns +The node id of the new node or 0 if an error happens. +.Pp +The functions +.Fn ng_connect_node +and +.Fn ng_connect_id +make a new hook connecting +.Fa ourhook +of the modules socket node +.Va snmp_node +to +.Fa peerhook +of the node identified by id +.Fa id +or name +.Fa node . +The functions return 0 on success or -1 otherwise. +.Pp +The function +.Fn ng_connect2_id +connects hook +.Fa ourhook +of the node with id +.Fa id +to hook +.Fa peerhook +of the node with id +.Fa peer . +The functions return 0 on success or -1 otherwise. +The function +.Fn ng_connect2_tee_id does the same as +.Fn ng_connect2_id +except, that it puts an unnamed tee node between the two nodes. +.Pp +The function +.Fn ng_rmhook +removes hook +.Fa hook +on the module's +.Va snmp_node . +The function +.Fn ng_rmhook_id +removes hook +.Fa hook +on the node with id +.Fa id . +The function +.Fn ng_rmhook_tee_id +additionally shuts down all tee nodes between the node and the first non-tee +peer. +.Pp +The function +.Fn ng_shutdown_id +destroys the given node. +.Sh FILES +.Bl -tag -width "XXXXXXXXX" +.It Pa /usr/share/bsnmp/defs/netgraph_tree.def +The description of the MIB tree implemented by +.Nm . +.It Pa /usr/share/bsnmp/mibs/BEGEMOT-NETGRAPH.txt +This is the MIB that is implemented by this module. +.Sh SEE ALSO +.Xr snmpmod 3 , +.Xr gensnmptree 1 +.Sh AUTHORS +.An Hartmut Brandt Aq harti@freebsd.org diff --git a/lib/libbsnmp/modules/snmp_netgraph/snmp_netgraph.c b/lib/libbsnmp/modules/snmp_netgraph/snmp_netgraph.c new file mode 100644 index 00000000000..4a70834ebab --- /dev/null +++ b/lib/libbsnmp/modules/snmp_netgraph/snmp_netgraph.c @@ -0,0 +1,1691 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * 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. + * + * 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. + * + * $FreeBSD$ + * + * Netgraph interface for SNMPd. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "snmpmod.h" +#include "snmp_netgraph.h" +#include "netgraph_tree.h" +#include "netgraph_oid.h" + +/* maximum message size */ +#define RESBUFSIZ 20000 + +/* default node name */ +#define NODENAME "NgSnmpd" + +/* my node Id */ +ng_ID_t snmp_node; +u_char *snmp_nodename; + +/* the Object Resource registration index */ +static u_int reg_index; +static const struct asn_oid oid_begemotNg = OIDX_begemotNg; + +/* configuration */ +/* this must be smaller than int32_t because the functions in libnetgraph + * falsely return an int */ +static size_t resbufsiz = RESBUFSIZ; +static u_int timeout = 1000; +static u_int debug_level; + +/* number of microseconds per clock tick */ +static struct clockinfo clockinfo; + +/* Csock buffers. Communication on the csock is asynchronuous. This means + * if we wait for a specific response, we may get other messages. Put these + * into a queue and execute them when we are idle. */ +struct csock_buf { + STAILQ_ENTRY(csock_buf) link; + struct ng_mesg *mesg; + char path[NG_PATHLEN + 1]; +}; +static STAILQ_HEAD(, csock_buf) csock_bufs = + STAILQ_HEAD_INITIALIZER(csock_bufs); + +/* + * We dispatch unsolicieted messages by node cookies and ids. + * So we must keep a list of hook names and dispatch functions. + */ +struct msgreg { + u_int32_t cookie; + ng_ID_t id; + ng_cookie_f *func; + void *arg; + const struct lmodule *mod; + SLIST_ENTRY(msgreg) link; +}; +static SLIST_HEAD(, msgreg) msgreg_list = + SLIST_HEAD_INITIALIZER(msgreg_list); + +/* + * Data messages are dispatched by hook names. + */ +struct datareg { + char hook[NG_HOOKLEN + 1]; + ng_hook_f *func; + void *arg; + const struct lmodule *mod; + SLIST_ENTRY(datareg) link; +}; +static SLIST_HEAD(, datareg) datareg_list = + SLIST_HEAD_INITIALIZER(datareg_list); + +/* the netgraph sockets */ +static int csock, dsock; +static void *csock_fd, *dsock_fd; + +/* our module handle */ +static struct lmodule *module; + +/* statistics */ +static u_int32_t stats[LEAF_begemotNgTooLargeDatas+1]; + +/* netgraph type list */ +struct ngtype { + char name[NG_TYPELEN + 1]; + struct asn_oid index; + TAILQ_ENTRY(ngtype) link; +}; +TAILQ_HEAD(ngtype_list, ngtype); + +static struct ngtype_list ngtype_list; +static u_int32_t ngtype_tick; + + +/* + * Register a function to receive unsolicited messages + */ +void * +ng_register_cookie(const struct lmodule *mod, u_int32_t cookie, ng_ID_t id, + ng_cookie_f *func, void *arg) +{ + struct msgreg *d; + + if ((d = malloc(sizeof(*d))) == NULL) + return (NULL); + + d->cookie = cookie; + d->id = id; + d->func = func; + d->arg = arg; + d->mod = mod; + + SLIST_INSERT_HEAD(&msgreg_list, d, link); + + return (d); +} + +/* + * Remove a registration. + */ +void +ng_unregister_cookie(void *dd) +{ + struct msgreg *d = dd; + + SLIST_REMOVE(&msgreg_list, d, msgreg, link); + free(d); +} + +/* + * Register a function for hook data. + */ +void * +ng_register_hook(const struct lmodule *mod, const char *hook, + ng_hook_f *func, void *arg) +{ + struct datareg *d; + + if ((d = malloc(sizeof(*d))) == NULL) + return (NULL); + + strcpy(d->hook, hook); + d->func = func; + d->arg = arg; + d->mod = mod; + + SLIST_INSERT_HEAD(&datareg_list, d, link); + + return (d); +} + +/* + * Unregister a hook function + */ +void +ng_unregister_hook(void *dd) +{ + struct datareg *d = dd; + + SLIST_REMOVE(&datareg_list, d, datareg, link); + free(d); +} + +/* + * Unregister all hooks and cookies for that module. Note: doesn't disconnect + * any hooks! + */ +void +ng_unregister_module(const struct lmodule *mod) +{ + struct msgreg *m, *m1; + struct datareg *d, *d1; + + m = SLIST_FIRST(&msgreg_list); + while (m != NULL) { + m1 = SLIST_NEXT(m, link); + if (m->mod == mod) { + SLIST_REMOVE(&msgreg_list, m, msgreg, link); + free(m); + } + m = m1; + } + + d = SLIST_FIRST(&datareg_list); + while (d != NULL) { + d1 = SLIST_NEXT(d, link); + if (d->mod == mod) { + SLIST_REMOVE(&datareg_list, d, datareg, link); + free(d); + } + d = d1; + } +} + +/* + * Dispatch a message to the correct module and delete it. More than one + * module can get a message. + */ +static void +csock_handle(struct ng_mesg *mesg, const char *path) +{ + struct msgreg *d, *d1; + u_int id; + int len; + + if (sscanf(path, "[%x]:%n", &id, &len) != 1 || + (u_int)len != strlen(path)) { + syslog(LOG_ERR, "cannot parse message path '%s'", path); + id = 0; + } + + d = SLIST_FIRST(&msgreg_list); + while (d != NULL) { + d1 = SLIST_NEXT(d, link); + if (d->cookie == mesg->header.typecookie && + (d->id == 0 || d->id == id || id == 0)) + (*d->func)(mesg, path, id, d->arg); + d = d1; + } + free(mesg); +} + +/* + * Input from the control socket. + */ +static struct ng_mesg * +csock_read(char *path) +{ + struct ng_mesg *mesg; + int ret, err; + + if ((mesg = malloc(resbufsiz + 1)) == NULL) { + stats[LEAF_begemotNgNoMems]++; + syslog(LOG_CRIT, "out of memory"); + errno = ENOMEM; + return (NULL); + } + if ((ret = NgRecvMsg(csock, mesg, resbufsiz + 1, path)) < 0) { + err = errno; + free(mesg); + if (errno == EWOULDBLOCK) { + errno = err; + return (NULL); + } + stats[LEAF_begemotNgMsgReadErrs]++; + syslog(LOG_WARNING, "read from csock: %m"); + errno = err; + return (NULL); + } + if (ret == 0) { + syslog(LOG_DEBUG, "node closed -- exiting"); + exit(0); + } + if ((size_t)ret > resbufsiz) { + stats[LEAF_begemotNgTooLargeMsgs]++; + syslog(LOG_WARNING, "ng message too large"); + free(mesg); + errno = EFBIG; + return (NULL); + } + return (mesg); +} + +static void +csock_input(int fd __unused, void *udata __unused) +{ + struct ng_mesg *mesg; + char path[NG_PATHLEN + 1]; + + if ((mesg = csock_read(path)) == NULL) + return; + + csock_handle(mesg, path); +} + +/* + * Write a message to a node. + */ +int +ng_output(const char *path, u_int cookie, u_int opcode, + const void *arg, size_t arglen) +{ + return (NgSendMsg(csock, path, (int)cookie, (int)opcode, arg, arglen)); +} +int +ng_output_node(const char *node, u_int cookie, u_int opcode, + const void *arg, size_t arglen) +{ + char path[NG_PATHLEN + 1]; + + sprintf(path, "%s:", node); + return (ng_output(path, cookie, opcode, arg, arglen)); +} +int +ng_output_id(ng_ID_t node, u_int cookie, u_int opcode, + const void *arg, size_t arglen) +{ + char path[NG_PATHLEN + 1]; + + sprintf(path, "[%x]:", node); + return (ng_output(path, cookie, opcode, arg, arglen)); +} + + + +/* + * Execute a synchronuous dialog with the csock. All message we receive, that + * do not match our request, are queue until the next call to the IDLE function. + */ +struct ng_mesg * +ng_dialog(const char *path, u_int cookie, u_int opcode, + const void *arg, size_t arglen) +{ + int token, err; + struct ng_mesg *mesg; + char rpath[NG_PATHLEN + 1]; + struct csock_buf *b; + struct timeval end, tv; + + if ((token = ng_output(path, cookie, opcode, arg, arglen)) < 0) + return (NULL); + + if (csock_fd) + fd_suspend(csock_fd); + + gettimeofday(&end, NULL); + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + timeradd(&end, &tv, &end); + for (;;) { + mesg = NULL; + gettimeofday(&tv, NULL); + if (timercmp(&tv, &end, >=)) { + block: + syslog(LOG_WARNING, "no response for request %u/%u", + cookie, opcode); + errno = EWOULDBLOCK; + break; + } + timersub(&end, &tv, &tv); + if (tv.tv_sec == 0 && tv.tv_usec < clockinfo.tick) + goto block; + + if (setsockopt(csock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) + syslog(LOG_WARNING, "setsockopt(SO_RCVTIMEO): %m"); + if ((mesg = csock_read(rpath)) == NULL) { + if (errno == EWOULDBLOCK) + continue; + break; + } + if (mesg->header.token == (u_int)token) + break; + if ((b = malloc(sizeof(*b))) == NULL) { + stats[LEAF_begemotNgNoMems]++; + syslog(LOG_ERR, "out of memory"); + free(mesg); + continue; + } + b->mesg = mesg; + strcpy(b->path, rpath); + STAILQ_INSERT_TAIL(&csock_bufs, b, link); + } + + tv.tv_sec = 0; + tv.tv_usec = 0; + if (setsockopt(csock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) + syslog(LOG_WARNING, "setsockopt(SO_RCVTIMEO,0): %m"); + + if (csock_fd) { + err = errno; + fd_resume(csock_fd); + errno = err; + } + + return (mesg); +} +struct ng_mesg * +ng_dialog_node(const char *node, u_int cookie, u_int opcode, + const void *arg, size_t arglen) +{ + char path[NG_PATHLEN + 1]; + + sprintf(path, "%s:", node); + return (ng_dialog(path, cookie, opcode, arg, arglen)); +} +struct ng_mesg * +ng_dialog_id(ng_ID_t id, u_int cookie, u_int opcode, + const void *arg, size_t arglen) +{ + char path[NG_PATHLEN + 1]; + + sprintf(path, "[%x]:", id); + return (ng_dialog(path, cookie, opcode, arg, arglen)); +} + + +/* + * Send a data message to a given hook. + */ +int +ng_send_data(const char *hook, const void *sndbuf, size_t sndlen) +{ + return (NgSendData(dsock, hook, sndbuf, sndlen)); +} + +/* + * Input from a data socket. Dispatch to the function for that hook. + */ +static void +dsock_input(int fd __unused, void *udata __unused) +{ + u_char *resbuf, embuf[100]; + ssize_t len; + char hook[NG_HOOKLEN + 1]; + struct datareg *d, *d1; + + if ((resbuf = malloc(resbufsiz + 1)) == NULL) { + stats[LEAF_begemotNgNoMems]++; + syslog(LOG_CRIT, "out of memory"); + (void)NgRecvData(fd, embuf, sizeof(embuf), hook); + errno = ENOMEM; + return; + } + if ((len = NgRecvData(fd, resbuf, resbufsiz + 1, hook)) == -1) { + stats[LEAF_begemotNgDataReadErrs]++; + syslog(LOG_ERR, "reading message: %m"); + free(resbuf); + return; + } + if (len == 0) { + free(resbuf); + return; + } + if ((size_t)len == resbufsiz + 1) { + stats[LEAF_begemotNgTooLargeDatas]++; + syslog(LOG_WARNING, "message too long"); + free(resbuf); + return; + } + + /* + * Dispatch message. Maybe dispatched to more than one function. + */ + d = SLIST_FIRST(&datareg_list); + while (d != NULL) { + d1 = SLIST_NEXT(d, link); + if (strcmp(hook, d->hook) == 0) + (*d->func)(hook, resbuf, len, d->arg); + d = d1; + } + + free(resbuf); +} + +/* + * The SNMP daemon is about to wait for an event. Look whether we have + * netgraph messages waiting. If yes, drain the queue. + */ +static void +ng_idle(void) +{ + struct csock_buf *b; + + /* execute waiting csock_bufs */ + while ((b = STAILQ_FIRST(&csock_bufs)) != NULL) { + STAILQ_REMOVE_HEAD(&csock_bufs, link); + csock_handle(b->mesg, b->path); + free(b); + } +} + +/* + * Called when the module is loaded. Returning a non-zero value means, + * rejecting the initialisation. + * + * We make the netgraph socket. + */ +static int +ng_init(struct lmodule *mod, int argc, char *argv[]) +{ + int name[2]; + size_t len; + + module = mod; + + if (argc == 0) { + if ((snmp_nodename = malloc(strlen(NODENAME) + 1)) == NULL) + return (ENOMEM); + strcpy(snmp_nodename, NODENAME); + } else { + if ((snmp_nodename = malloc(NG_NODELEN + 1)) == NULL) + return (ENOMEM); + snprintf(snmp_nodename, NG_NODELEN + 1, "%s", argv[0]); + } + + /* fetch clockinfo (for the number of microseconds per tick) */ + name[0] = CTL_KERN; + name[1] = KERN_CLOCKRATE; + len = sizeof(clockinfo); + if (sysctl(name, 2, &clockinfo, &len, NULL, 0) == -1) + return (errno); + + TAILQ_INIT(&ngtype_list); + + return (0); +} + +/* + * Get the node Id/name/type of a node. + */ +ng_ID_t +ng_node_id(const char *path) +{ + struct ng_mesg *resp; + ng_ID_t id; + + if ((resp = ng_dialog(path, NGM_GENERIC_COOKIE, NGM_NODEINFO, + NULL, 0)) == NULL) + return (0); + id = ((struct nodeinfo *)(void *)resp->data)->id; + free(resp); + return (id); +} +ng_ID_t +ng_node_id_node(const char *node) +{ + struct ng_mesg *resp; + ng_ID_t id; + + if ((resp = ng_dialog_node(node, NGM_GENERIC_COOKIE, NGM_NODEINFO, + NULL, 0)) == NULL) + return (0); + id = ((struct nodeinfo *)(void *)resp->data)->id; + free(resp); + return (id); +} +ng_ID_t +ng_node_name(ng_ID_t id, char *name) +{ + struct ng_mesg *resp; + + if ((resp = ng_dialog_id(id, NGM_GENERIC_COOKIE, NGM_NODEINFO, + NULL, 0)) == NULL) + return (0); + strcpy(name, ((struct nodeinfo *)(void *)resp->data)->name); + free(resp); + return (id); + +} +ng_ID_t +ng_node_type(ng_ID_t id, char *type) +{ + struct ng_mesg *resp; + + if ((resp = ng_dialog_id(id, NGM_GENERIC_COOKIE, NGM_NODEINFO, + NULL, 0)) == NULL) + return (0); + strcpy(type, ((struct nodeinfo *)(void *)resp->data)->type); + free(resp); + return (id); +} + +/* + * Connect our node to some other node + */ +int +ng_connect_node(const char *node, const char *ourhook, const char *peerhook) +{ + struct ngm_connect conn; + + snprintf(conn.path, NG_PATHLEN + 1, "%s:", node); + snprintf(conn.ourhook, NG_HOOKLEN + 1, ourhook); + snprintf(conn.peerhook, NG_HOOKLEN + 1, peerhook); + return (NgSendMsg(csock, ".:", + NGM_GENERIC_COOKIE, NGM_CONNECT, &conn, sizeof(conn))); +} +int +ng_connect_id(ng_ID_t id, const char *ourhook, const char *peerhook) +{ + struct ngm_connect conn; + + snprintf(conn.path, NG_PATHLEN + 1, "[%x]:", id); + snprintf(conn.ourhook, NG_HOOKLEN + 1, ourhook); + snprintf(conn.peerhook, NG_HOOKLEN + 1, peerhook); + return (NgSendMsg(csock, ".:", + NGM_GENERIC_COOKIE, NGM_CONNECT, &conn, sizeof(conn))); +} + +int +ng_connect2_id(ng_ID_t id, ng_ID_t peer, const char *ourhook, + const char *peerhook) +{ + struct ngm_connect conn; + char path[NG_PATHLEN + 1]; + + snprintf(path, NG_PATHLEN + 1, "[%x]:", id); + + snprintf(conn.path, NG_PATHLEN + 1, "[%x]:", peer); + snprintf(conn.ourhook, NG_HOOKLEN + 1, ourhook); + snprintf(conn.peerhook, NG_HOOKLEN + 1, peerhook); + return (NgSendMsg(csock, path, + NGM_GENERIC_COOKIE, NGM_CONNECT, &conn, sizeof(conn))); +} + +int +ng_connect2_tee_id(ng_ID_t id, ng_ID_t peer, const char *ourhook, + const char *peerhook) +{ + struct ngm_connect conn; + char path[NG_PATHLEN + 1]; + ng_ID_t tee; + + if ((tee = ng_mkpeer_id(id, NULL, "tee", ourhook, "left")) == 0) + return (-1); + + snprintf(path, NG_PATHLEN + 1, "[%x]:", tee); + + snprintf(conn.path, NG_PATHLEN + 1, "[%x]:", peer); + snprintf(conn.ourhook, NG_HOOKLEN + 1, "right"); + snprintf(conn.peerhook, NG_HOOKLEN + 1, peerhook); + return (NgSendMsg(csock, path, + NGM_GENERIC_COOKIE, NGM_CONNECT, &conn, sizeof(conn))); +} + +/* + * Ensure that a node of type 'type' is connected to 'hook' of 'node' + * and return its node id. tee nodes between node and the target node + * are skipped. If the type is wrong, or the hook is a dead-end return 0. + * If type is NULL, it is not checked. + */ +static ng_ID_t +ng_next_node_id_internal(ng_ID_t node, const char *type, const char *hook, + int skip_tee) +{ + struct ng_mesg *resp; + struct hooklist *hooklist; + u_int i; + + if ((resp = ng_dialog_id(node, NGM_GENERIC_COOKIE, NGM_LISTHOOKS, + NULL, 0)) == NULL) { + syslog(LOG_ERR, "get hook list: %m"); + exit(1); + } + hooklist = (struct hooklist *)(void *)resp->data; + + for (i = 0; i < hooklist->nodeinfo.hooks; i++) + if (strcmp(hooklist->link[i].ourhook, hook) == 0) + break; + + if (i == hooklist->nodeinfo.hooks) { + free(resp); + return (0); + } + + node = hooklist->link[i].nodeinfo.id; + + if (skip_tee && strcmp(hooklist->link[i].nodeinfo.type, "tee") == 0) { + if (strcmp(hooklist->link[i].peerhook, "left") == 0) + node = ng_next_node_id(node, type, "right"); + else if (strcmp(hooklist->link[i].peerhook, "right") == 0) + node = ng_next_node_id(node, type, "left"); + else if (type != NULL && + strcmp(hooklist->link[i].nodeinfo.type, type) != 0) + node = 0; + + } else if (type != NULL && + strcmp(hooklist->link[i].nodeinfo.type, type) != 0) + node = 0; + + free(resp); + + return (node); +} + +/* + * Ensure that a node of type 'type' is connected to 'hook' of 'node' + * and return its node id. tee nodes between node and the target node + * are skipped. If the type is wrong, or the hook is a dead-end return 0. + * If type is NULL, it is not checked. + */ +ng_ID_t +ng_next_node_id(ng_ID_t node, const char *type, const char *hook) +{ + return (ng_next_node_id_internal(node, type, hook, 1)); +} + +ng_ID_t +ng_mkpeer_id(ng_ID_t id, const char *nodename, const char *type, + const char *hook, const char *peerhook) +{ + char path[NG_PATHLEN + 1]; + struct ngm_mkpeer mkpeer; + struct ngm_name name; + + strcpy(mkpeer.type, type); + strcpy(mkpeer.ourhook, hook); + strcpy(mkpeer.peerhook, peerhook); + + sprintf(path, "[%x]:", id); + if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, NGM_MKPEER, + &mkpeer, sizeof(mkpeer)) == -1) + return (0); + + if ((id = ng_next_node_id_internal(id, NULL, hook, 0)) == NULL) + return (0); + + if (nodename != NULL) { + strcpy(name.name, nodename); + sprintf(path, "[%x]:", id); + if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, NGM_NAME, + &name, sizeof(name)) == -1) + return (0); + } + return (id); +} + +/* + * SHutdown node + */ +int +ng_shutdown_id(ng_ID_t id) +{ + char path[NG_PATHLEN + 1]; + + sprintf(path, "[%x]:", id); + return (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, + NGM_SHUTDOWN, NULL, 0)); +} + +/* + * Disconnect one of our hooks + */ +int +ng_rmhook(const char *ourhook) +{ + struct ngm_rmhook rmhook; + + snprintf(rmhook.ourhook, NG_HOOKLEN + 1, "%s", ourhook); + return (NgSendMsg(csock, ".:", + NGM_GENERIC_COOKIE, NGM_RMHOOK, &rmhook, sizeof(rmhook))); +} + +/* + * Disconnect a hook of a node + */ +int +ng_rmhook_id(ng_ID_t id, const char *hook) +{ + struct ngm_rmhook rmhook; + char path[NG_PATHLEN + 1]; + + snprintf(rmhook.ourhook, NG_HOOKLEN + 1, "%s", hook); + sprintf(path, "[%x]:", id); + return (NgSendMsg(csock, path, + NGM_GENERIC_COOKIE, NGM_RMHOOK, &rmhook, sizeof(rmhook))); +} + +/* + * Disconnect a hook and shutdown all tee nodes that were connected to that + * hook. + */ +int +ng_rmhook_tee_id(ng_ID_t node, const char *hook) +{ + struct ng_mesg *resp; + struct hooklist *hooklist; + u_int i; + int first = 1; + ng_ID_t next_node; + const char *next_hook; + + again: + /* if we have just shutdown a tee node, which had no other hooks + * connected, the node id may already be wrong here. */ + if ((resp = ng_dialog_id(node, NGM_GENERIC_COOKIE, NGM_LISTHOOKS, + NULL, 0)) == NULL) + return (0); + + hooklist = (struct hooklist *)(void *)resp->data; + + for (i = 0; i < hooklist->nodeinfo.hooks; i++) + if (strcmp(hooklist->link[i].ourhook, hook) == 0) + break; + + if (i == hooklist->nodeinfo.hooks) { + free(resp); + return (0); + } + + next_node = 0; + next_hook = NULL; + if (strcmp(hooklist->link[i].nodeinfo.type, "tee") == 0) { + if (strcmp(hooklist->link[i].peerhook, "left") == 0) { + next_node = hooklist->link[i].nodeinfo.id; + next_hook = "right"; + } else if (strcmp(hooklist->link[i].peerhook, "right") == 0) { + next_node = hooklist->link[i].nodeinfo.id; + next_hook = "left"; + } + } + free(resp); + + if (first) { + ng_rmhook_id(node, hook); + first = 0; + } else { + ng_shutdown_id(node); + } + if ((node = next_node) == 0) + return (0); + hook = next_hook; + + goto again; +} + +/* + * Get the peer hook of a hook on a given node. Skip any tee nodes in between + */ +int +ng_peer_hook_id(ng_ID_t node, const char *hook, char *peerhook) +{ + struct ng_mesg *resp; + struct hooklist *hooklist; + u_int i; + int ret; + + if ((resp = ng_dialog_id(node, NGM_GENERIC_COOKIE, NGM_LISTHOOKS, + NULL, 0)) == NULL) { + syslog(LOG_ERR, "get hook list: %m"); + exit(1); + } + hooklist = (struct hooklist *)(void *)resp->data; + + for (i = 0; i < hooklist->nodeinfo.hooks; i++) + if (strcmp(hooklist->link[i].ourhook, hook) == 0) + break; + + if (i == hooklist->nodeinfo.hooks) { + free(resp); + return (-1); + } + + node = hooklist->link[i].nodeinfo.id; + + ret = 0; + if (strcmp(hooklist->link[i].nodeinfo.type, "tee") == 0) { + if (strcmp(hooklist->link[i].peerhook, "left") == 0) + ret = ng_peer_hook_id(node, "right", peerhook); + else if (strcmp(hooklist->link[i].peerhook, "right") == 0) + ret = ng_peer_hook_id(node, "left", peerhook); + else + strcpy(peerhook, hooklist->link[i].peerhook); + + } else + strcpy(peerhook, hooklist->link[i].peerhook); + + free(resp); + + return (ret); +} + + +/* + * Now the module is started. Select on the sockets, so that we can get + * unsolicited input. + */ +static void +ng_start(void) +{ + if (snmp_node == 0) { + if (NgMkSockNode(snmp_nodename, &csock, &dsock) < 0) { + syslog(LOG_ERR, "NgMkSockNode: %m"); + exit(1); + } + snmp_node = ng_node_id(".:"); + } + + if ((csock_fd = fd_select(csock, csock_input, NULL, module)) == NULL) { + syslog(LOG_ERR, "fd_select failed on csock: %m"); + return; + } + if ((dsock_fd = fd_select(dsock, dsock_input, NULL, module)) == NULL) { + syslog(LOG_ERR, "fd_select failed on dsock: %m"); + return; + } + + reg_index = or_register(&oid_begemotNg, + "The MIB for the NetGraph access module for SNMP.", module); + +} + +/* + * Called, when the module is to be unloaded after it was successfully loaded + */ +static int +ng_fini(void) +{ + struct ngtype *t; + + while ((t = TAILQ_FIRST(&ngtype_list)) != NULL) { + TAILQ_REMOVE(&ngtype_list, t, link); + free(t); + } + + if (csock_fd != NULL) + fd_deselect(csock_fd); + (void)close(csock); + + if (dsock_fd != NULL) + fd_deselect(dsock_fd); + (void)close(dsock); + + free(snmp_nodename); + + or_unregister(reg_index); + + return (0); +} + +const struct snmp_module config = { + "This module implements access to the netgraph sub-system", + ng_init, + ng_fini, + ng_idle, + NULL, + NULL, + ng_start, + NULL, + netgraph_ctree, + netgraph_CTREE_SIZE, + NULL +}; + +int +op_ng_config(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + int ret; + + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + /* + * Come here for GET, GETNEXT and COMMIT + */ + switch (which) { + + case LEAF_begemotNgControlNodeName: + return (string_get(value, snmp_nodename, -1)); + + case LEAF_begemotNgResBufSiz: + value->v.integer = resbufsiz; + break; + + case LEAF_begemotNgTimeout: + value->v.integer = timeout; + break; + + case LEAF_begemotNgDebugLevel: + value->v.uint32 = debug_level; + break; + + default: + abort(); + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_SET: + switch (which) { + + case LEAF_begemotNgControlNodeName: + /* only at initialisation */ + if (community != COMM_INITIALIZE) + return (SNMP_ERR_NOT_WRITEABLE); + + if (snmp_node != 0) + return (SNMP_ERR_NOT_WRITEABLE); + + if ((ret = string_save(value, ctx, -1, &snmp_nodename)) + != SNMP_ERR_NOERROR) + return (ret); + + if (NgMkSockNode(snmp_nodename, &csock, &dsock) < 0) { + syslog(LOG_ERR, "NgMkSockNode: %m"); + string_rollback(ctx, &snmp_nodename); + return (SNMP_ERR_GENERR); + } + snmp_node = ng_node_id(".:"); + + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNgResBufSiz: + ctx->scratch->int1 = resbufsiz; + if (value->v.integer < 1024 || + value->v.integer > 0x10000) + return (SNMP_ERR_WRONG_VALUE); + resbufsiz = value->v.integer; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNgTimeout: + ctx->scratch->int1 = timeout; + if (value->v.integer < 10 || + value->v.integer > 10000) + return (SNMP_ERR_WRONG_VALUE); + timeout = value->v.integer; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNgDebugLevel: + ctx->scratch->int1 = debug_level; + debug_level = value->v.uint32; + NgSetDebug(debug_level); + return (SNMP_ERR_NOERROR); + } + abort(); + + case SNMP_OP_ROLLBACK: + switch (which) { + + case LEAF_begemotNgControlNodeName: + string_rollback(ctx, &snmp_nodename); + close(csock); + close(dsock); + snmp_node = 0; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNgResBufSiz: + resbufsiz = ctx->scratch->int1; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNgTimeout: + timeout = ctx->scratch->int1; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNgDebugLevel: + debug_level = ctx->scratch->int1; + NgSetDebug(debug_level); + return (SNMP_ERR_NOERROR); + } + abort(); + + case SNMP_OP_COMMIT: + switch (which) { + + case LEAF_begemotNgControlNodeName: + string_commit(ctx); + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNgResBufSiz: + case LEAF_begemotNgTimeout: + case LEAF_begemotNgDebugLevel: + return (SNMP_ERR_NOERROR); + } + abort(); + } + abort(); +} + +int +op_ng_stats(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: + value->v.uint32 = stats[value->var.subs[sub - 1] - 1]; + return (SNMP_ERR_NOERROR); + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + abort(); + } + abort(); +} + +/* + * Netgraph type table + */ +static int +fetch_types(void) +{ + struct ngtype *t; + struct typelist *typelist; + struct ng_mesg *resp; + u_int u, i; + + if (this_tick <= ngtype_tick) + return (0); + + while ((t = TAILQ_FIRST(&ngtype_list)) != NULL) { + TAILQ_REMOVE(&ngtype_list, t, link); + free(t); + } + + if ((resp = ng_dialog_id(snmp_node, NGM_GENERIC_COOKIE, + NGM_LISTTYPES, NULL, 0)) == NULL) + return (SNMP_ERR_GENERR); + typelist = (struct typelist *)(void *)resp->data; + + for (u = 0; u < typelist->numtypes; u++) { + if ((t = malloc(sizeof(*t))) == NULL) { + free(resp); + return (SNMP_ERR_GENERR); + } + strcpy(t->name, typelist->typeinfo[u].type_name); + t->index.subs[0] = strlen(t->name); + t->index.len = t->index.subs[0] + 1; + for (i = 0; i < t->index.subs[0]; i++) + t->index.subs[i + 1] = t->name[i]; + + INSERT_OBJECT_OID(t, &ngtype_list); + } + + ngtype_tick = this_tick; + + free(resp); + return (0); +} + +/* + * Try to load the netgraph type with the given name. We assume, that + * type 'type' is implemented in the kernel module 'ng_type'. + */ +static int +ngtype_load(const u_char *name, size_t namelen) +{ + char *mod; + int ret; + + if ((mod = malloc(namelen + 4)) == NULL) + return (-1); + strcpy(mod, "ng_"); + strncpy(mod + 3, name, namelen); + mod[namelen + 3] = '\0'; + + ret = kldload(mod); + free(mod); + return (ret); +} + +/* + * Unload a netgraph type. + */ +static int +ngtype_unload(const u_char *name, size_t namelen) +{ + char *mod; + int id; + + if ((mod = malloc(namelen + 4)) == NULL) + return (-1); + strcpy(mod, "ng_"); + strncpy(mod + 3, name, namelen); + mod[namelen + 3] = '\0'; + + if ((id = kldfind(mod)) == -1) { + free(mod); + return (-1); + } + free(mod); + return (kldunload(id)); +} + +int +op_ng_type(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + struct ngtype *t; + u_char *name; + size_t namelen; + int status = 1; + int ret; + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((ret = fetch_types()) != 0) + return (ret); + if ((t = NEXT_OBJECT_OID(&ngtype_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &t->index); + break; + + case SNMP_OP_GET: + if ((ret = fetch_types()) != 0) + return (ret); + if ((t = FIND_OBJECT_OID(&ngtype_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if (index_decode(&value->var, sub, iidx, &name, &namelen)) + return (SNMP_ERR_NO_CREATION); + if (namelen == 0 || namelen > NG_TYPELEN) { + free(name); + return (SNMP_ERR_NO_CREATION); + } + if ((ret = fetch_types()) != 0) { + free(name); + return (ret); + } + t = FIND_OBJECT_OID(&ngtype_list, &value->var, sub); + + if (which != LEAF_begemotNgTypeStatus) { + free(name); + if (t != NULL) + return (SNMP_ERR_NOT_WRITEABLE); + return (SNMP_ERR_NO_CREATION); + } + if (!TRUTH_OK(value->v.integer)) { + free(name); + return (SNMP_ERR_WRONG_VALUE); + } + ctx->scratch->int1 = TRUTH_GET(value->v.integer); + ctx->scratch->int1 |= (t != NULL) << 1; + ctx->scratch->ptr2 = name; + ctx->scratch->int2 = namelen; + + if (t == NULL) { + /* type not loaded */ + if (ctx->scratch->int1 & 1) { + /* request to load */ + if (ngtype_load(name, namelen) == -1) { + free(name); + if (errno == ENOENT) + return (SNMP_ERR_INCONS_NAME); + else + return (SNMP_ERR_GENERR); + } + } + } else { + /* is type loaded */ + if (!(ctx->scratch->int1 & 1)) { + /* request to unload */ + if (ngtype_unload(name, namelen) == -1) { + free(name); + return (SNMP_ERR_GENERR); + } + } + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + ret = SNMP_ERR_NOERROR; + if (!(ctx->scratch->int1 & 2)) { + /* did not exist */ + if (ctx->scratch->int1 & 1) { + /* request to load - unload */ + if (ngtype_unload(ctx->scratch->ptr2, + ctx->scratch->int2) == -1) + ret = SNMP_ERR_UNDO_FAILED; + } + } else { + /* did exist */ + if (!(ctx->scratch->int1 & 1)) { + /* request to unload - reload */ + if (ngtype_load(ctx->scratch->ptr2, + ctx->scratch->int2) == -1) + ret = SNMP_ERR_UNDO_FAILED; + } + } + free(ctx->scratch->ptr2); + return (ret); + + case SNMP_OP_COMMIT: + free(ctx->scratch->ptr2); + return (SNMP_ERR_NOERROR); + + default: + abort(); + } + + /* + * Come here for GET and COMMIT + */ + switch (which) { + + case LEAF_begemotNgTypeStatus: + value->v.integer = status; + break; + + default: + abort(); + } + return (SNMP_ERR_NOERROR); +} + +/* + * Implement the node table + */ +static int +find_node(const struct asn_oid *oid, u_int sub, struct nodeinfo *info) +{ + ng_ID_t id = oid->subs[sub]; + struct ng_mesg *resp; + + if ((resp = ng_dialog_id(id, NGM_GENERIC_COOKIE, NGM_NODEINFO, + NULL, 0)) == NULL) + return (-1); + + *info = *(struct nodeinfo *)(void *)resp->data; + free(resp); + return (0); +} + +static int +ncmp(const void *p1, const void *p2) +{ + const struct nodeinfo *i1 = p1; + const struct nodeinfo *i2 = p2; + + if (i1->id < i2->id) + return (-1); + if (i1->id > i2->id) + return (+1); + return (0); +} + +static int +find_node_next(const struct asn_oid *oid, u_int sub, struct nodeinfo *info) +{ + u_int idxlen = oid->len - sub; + struct ng_mesg *resp; + struct namelist *list; + ng_ID_t id; + u_int i; + + if ((resp = ng_dialog_id(snmp_node, NGM_GENERIC_COOKIE, NGM_LISTNODES, + NULL, 0)) == NULL) + return (-1); + list = (struct namelist *)(void *)resp->data; + + qsort(list->nodeinfo, list->numnames, sizeof(list->nodeinfo[0]), ncmp); + + if (idxlen == 0) { + if (list->numnames == 0) { + free(resp); + return (-1); + } + *info = list->nodeinfo[0]; + free(resp); + return (0); + } + id = oid->subs[sub]; + + for (i = 0; i < list->numnames; i++) + if (list->nodeinfo[i].id > id) { + *info = list->nodeinfo[i]; + free(resp); + return (0); + } + + free(resp); + return (-1); +} + +int +op_ng_node(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + u_int idxlen = value->var.len - sub; + struct nodeinfo nodeinfo; + + switch (op) { + + case SNMP_OP_GETNEXT: + if (find_node_next(&value->var, sub, &nodeinfo) == -1) + return (SNMP_ERR_NOSUCHNAME); + value->var.len = sub + 1; + value->var.subs[sub] = nodeinfo.id; + break; + + case SNMP_OP_GET: + if (idxlen != 1) + return (SNMP_ERR_NOSUCHNAME); + if (find_node(&value->var, sub, &nodeinfo) == -1) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if (idxlen != 1) + return (SNMP_ERR_NO_CREATION); + if (find_node(&value->var, sub, &nodeinfo) == -1) + return (SNMP_ERR_NO_CREATION); + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + default: + abort(); + } + + /* + * Come here for GET and COMMIT + */ + switch (which) { + + case LEAF_begemotNgNodeStatus: + value->v.integer = 1; + break; + case LEAF_begemotNgNodeName: + return (string_get(value, nodeinfo.name, -1)); + case LEAF_begemotNgNodeType: + return (string_get(value, nodeinfo.type, -1)); + case LEAF_begemotNgNodeHooks: + value->v.uint32 = nodeinfo.hooks; + break; + + default: + abort(); + } + return (SNMP_ERR_NOERROR); +} + +/* + * Implement the hook table + */ +static int +find_hook(int32_t id, const u_char *hook, size_t hooklen, struct linkinfo *info) +{ + struct ng_mesg *resp; + struct hooklist *list; + u_int i; + + if ((resp = ng_dialog_id(id, NGM_GENERIC_COOKIE, + NGM_LISTHOOKS, NULL, 0)) == NULL) + return (-1); + + list = (struct hooklist *)(void *)resp->data; + + for (i = 0; i < list->nodeinfo.hooks; i++) { + if (strlen(list->link[i].ourhook) == hooklen && + strncmp(list->link[i].ourhook, hook, hooklen) == 0) { + *info = list->link[i]; + free(resp); + return (0); + } + } + free(resp); + return (-1); +} + +static int +hook_cmp(const void *p1, const void *p2) +{ + const struct linkinfo *i1 = p1; + const struct linkinfo *i2 = p2; + + if (strlen(i1->ourhook) < strlen(i2->ourhook)) + return (-1); + if (strlen(i1->ourhook) > strlen(i2->ourhook)) + return (+1); + return (strcmp(i1->ourhook, i2->ourhook)); +} + +static int +find_hook_next(const struct asn_oid *oid, u_int sub, struct nodeinfo *nodeinfo, + struct linkinfo *linkinfo) +{ + u_int idxlen = oid->len - sub; + struct namelist *list; + struct ng_mesg *resp; + struct hooklist *hooks; + struct ng_mesg *resp1; + u_int node_index; + struct asn_oid idx; + u_int i, j; + + /* + * Get and sort Node list + */ + if ((resp = ng_dialog_id(snmp_node, NGM_GENERIC_COOKIE, NGM_LISTNODES, + NULL, 0)) == NULL) + return (-1); + list = (struct namelist *)(void *)resp->data; + + qsort(list->nodeinfo, list->numnames, sizeof(list->nodeinfo[0]), ncmp); + + /* + * If we have no index, take the first node and return the + * first hook. + */ + if (idxlen == 0) { + node_index = 0; + goto return_first_hook; + } + + /* + * Locate node + */ + for (node_index = 0; node_index < list->numnames; node_index++) + if (list->nodeinfo[node_index].id >= oid->subs[sub]) + break; + + /* + * If we have only the node part of the index take, or + * there is no node with that Id, take the first hook of that node. + */ + if (idxlen == 1 || node_index >= list->numnames || + list->nodeinfo[node_index].id > oid->subs[sub]) + goto return_first_hook; + + /* + * We had an exact match on the node id and have (at last part) + * of the hook name index. Loop through the hooks of the node + * and find the next one. + */ + if ((resp1 = ng_dialog_id(list->nodeinfo[node_index].id, + NGM_GENERIC_COOKIE, NGM_LISTHOOKS, NULL, 0)) == NULL) { + free(resp); + return (-1); + } + hooks = (struct hooklist *)(void *)resp1->data; + if (hooks->nodeinfo.hooks > 0) { + qsort(hooks->link, hooks->nodeinfo.hooks, + sizeof(hooks->link[0]), hook_cmp); + for (i = 0; i < hooks->nodeinfo.hooks; i++) { + idx.len = strlen(hooks->link[i].ourhook) + 1; + idx.subs[0] = idx.len - 1; + for (j = 0; j < idx.len; j++) + idx.subs[j + 1] = hooks->link[i].ourhook[j]; + if (index_compare(oid, sub + 1, &idx) < 0) + break; + } + if (i < hooks->nodeinfo.hooks) { + *nodeinfo = hooks->nodeinfo; + *linkinfo = hooks->link[i]; + + free(resp); + free(resp1); + return (0); + } + } + + /* no hook found larger than the index on the index node - take + * first hook of next node */ + free(resp1); + node_index++; + + return_first_hook: + while (node_index < list->numnames) { + if ((resp1 = ng_dialog_id(list->nodeinfo[node_index].id, + NGM_GENERIC_COOKIE, NGM_LISTHOOKS, NULL, 0)) == NULL) + break; + hooks = (struct hooklist *)(void *)resp1->data; + if (hooks->nodeinfo.hooks > 0) { + qsort(hooks->link, hooks->nodeinfo.hooks, + sizeof(hooks->link[0]), hook_cmp); + + *nodeinfo = hooks->nodeinfo; + *linkinfo = hooks->link[0]; + + free(resp); + free(resp1); + return (0); + } + + /* if we don't have hooks, try next node */ + free(resp1); + node_index++; + } + + free(resp); + return (-1); +} + +int +op_ng_hook(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + struct linkinfo linkinfo; + struct nodeinfo nodeinfo; + u_int32_t lid; + u_char *hook; + size_t hooklen; + u_int i; + + switch (op) { + + case SNMP_OP_GETNEXT: + if (find_hook_next(&value->var, sub, &nodeinfo, &linkinfo) == -1) + return (SNMP_ERR_NOSUCHNAME); + + value->var.len = sub + 1 + 1 + strlen(linkinfo.ourhook); + value->var.subs[sub] = nodeinfo.id; + value->var.subs[sub + 1] = strlen(linkinfo.ourhook); + for (i = 0; i < strlen(linkinfo.ourhook); i++) + value->var.subs[sub + i + 2] = + linkinfo.ourhook[i]; + break; + + case SNMP_OP_GET: + if (index_decode(&value->var, sub, iidx, &lid, + &hook, &hooklen)) + return (SNMP_ERR_NOSUCHNAME); + if (find_hook(lid, hook, hooklen, &linkinfo) == -1) { + free(hook); + return (SNMP_ERR_NOSUCHNAME); + } + free(hook); + break; + + case SNMP_OP_SET: + if (index_decode(&value->var, sub, iidx, &lid, + &hook, &hooklen)) + return (SNMP_ERR_NO_CREATION); + if (find_hook(lid, hook, hooklen, &linkinfo) == -1) { + free(hook); + return (SNMP_ERR_NO_CREATION); + } + free(hook); + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + default: + abort(); + + } + + switch (which) { + + case LEAF_begemotNgHookStatus: + value->v.integer = 1; + break; + case LEAF_begemotNgHookPeerNodeId: + value->v.uint32 = linkinfo.nodeinfo.id; + break; + case LEAF_begemotNgHookPeerHook: + return (string_get(value, linkinfo.peerhook, -1)); + case LEAF_begemotNgHookPeerType: + return (string_get(value, linkinfo.nodeinfo.type, -1)); + default: + abort(); + } + return (SNMP_ERR_NOERROR); +} diff --git a/lib/libbsnmp/modules/snmp_netgraph/snmp_netgraph.h b/lib/libbsnmp/modules/snmp_netgraph/snmp_netgraph.h new file mode 100644 index 00000000000..21e553c3091 --- /dev/null +++ b/lib/libbsnmp/modules/snmp_netgraph/snmp_netgraph.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * 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. + * + * 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. + * + * $FreeBSD$ + * + * Netgraph interface for SNMPd. Exported stuff. + */ +#ifndef SNMP_NETGRAPH_H_ +#define SNMP_NETGRAPH_H_ + +#include + +extern ng_ID_t snmp_node; +extern u_char *snmp_nodename; + +typedef void ng_cookie_f(const struct ng_mesg *, const char *, ng_ID_t, void *); +typedef void ng_hook_f(const char *, const u_char *, size_t, void *); + +void *ng_register_cookie(const struct lmodule *, u_int32_t cookie, + ng_ID_t, ng_cookie_f *, void *); +void ng_unregister_cookie(void *reg); + +void *ng_register_hook(const struct lmodule *, const char *, + ng_hook_f *, void *); +void ng_unregister_hook(void *reg); + +void ng_unregister_module(const struct lmodule *); + +int ng_output(const char *path, u_int cookie, u_int opcode, + const void *arg, size_t arglen); +int ng_output_node(const char *node, u_int cookie, u_int opcode, + const void *arg, size_t arglen); +int ng_output_id(ng_ID_t node, u_int cookie, u_int opcode, + const void *arg, size_t arglen); + +struct ng_mesg *ng_dialog(const char *path, u_int cookie, u_int opcode, + const void *arg, size_t arglen); +struct ng_mesg *ng_dialog_node(const char *node, u_int cookie, u_int opcode, + const void *arg, size_t arglen); +struct ng_mesg *ng_dialog_id(ng_ID_t id, u_int cookie, u_int opcode, + const void *arg, size_t arglen); + +int ng_send_data(const char *hook, const void *sndbuf, size_t sndlen); + +ng_ID_t ng_mkpeer_id(ng_ID_t, const char *name, const char *type, + const char *hook, const char *peerhook); +int ng_connect_node(const char *node, const char *ourhook, const char *peerhook); +int ng_connect_id(ng_ID_t id, const char *ourhook, const char *peerhook); +int ng_connect2_id(ng_ID_t id, ng_ID_t peer, const char *ourhook, + const char *peerhook); +int ng_connect2_tee_id(ng_ID_t id, ng_ID_t peer, const char *ourhook, + const char *peerhook); +int ng_rmhook(const char *ourhook); +int ng_rmhook_id(ng_ID_t, const char *); +int ng_rmhook_tee_id(ng_ID_t, const char *); +int ng_shutdown_id(ng_ID_t); + +ng_ID_t ng_next_node_id(ng_ID_t node, const char *type, const char *hook); +ng_ID_t ng_node_id(const char *path); +ng_ID_t ng_node_id_node(const char *node); +ng_ID_t ng_node_name(ng_ID_t, char *); +ng_ID_t ng_node_type(ng_ID_t, char *); +int ng_peer_hook_id(ng_ID_t, const char *, char *); + +#endif diff --git a/usr.sbin/bsnmpd/modules/Makefile b/usr.sbin/bsnmpd/modules/Makefile new file mode 100644 index 00000000000..ad5df5f209b --- /dev/null +++ b/usr.sbin/bsnmpd/modules/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../contrib/bsnmp/snmpd + +SUBDIR= snmp_mibII \ + snmp_netgraph + +INCS= snmpmod.h +INCSDIR= ${INCLUDEDIR}/bsnmp + +.include diff --git a/usr.sbin/bsnmpd/modules/Makefile.inc b/usr.sbin/bsnmpd/modules/Makefile.inc new file mode 100644 index 00000000000..c9d6718cfa2 --- /dev/null +++ b/usr.sbin/bsnmpd/modules/Makefile.inc @@ -0,0 +1,16 @@ +# $FreeBSD$ + +NOINSTALLLIB= yes +NOPROFILE= yes + +LIB= snmp_${MOD} +SHLIB_NAME= snmp_${MOD}.so.${SHLIB_MAJOR} + +SRCS:= ${MOD}_oid.h ${MOD}_tree.c ${MOD}_tree.h ${SRCS} + +MIBSDIR= ${SHAREDIR}/bsnmp/mibs +DEFSDIR= ${SHAREDIR}/bsnmp/defs + +FILESGROUPS += DEFS MIBS + +.include "../Makefile.inc" diff --git a/usr.sbin/bsnmpd/modules/snmp_mibII/Makefile b/usr.sbin/bsnmpd/modules/snmp_mibII/Makefile new file mode 100644 index 00000000000..7fa524a93c8 --- /dev/null +++ b/usr.sbin/bsnmpd/modules/snmp_mibII/Makefile @@ -0,0 +1,19 @@ +# $FreeBSD$ +# +# Author: Harti Brandt + +CONTRIB=${.CURDIR}/../../../../contrib/bsnmp/snmp_mibII +.PATH: ${CONTRIB} + +MOD= mibII +SRCS= mibII.c mibII_ifmib.c mibII_ip.c mibII_interfaces.c \ + mibII_ipaddr.c mibII_ifstack.c mibII_rcvaddr.c \ + mibII_nettomedia.c mibII_tcp.c mibII_udp.c mibII_route.c +MAN= snmp_mibII.3 + +DEFS= ${MOD}_tree.def +INCS= snmp_${MOD}.h + +CFLAGS+= -I${INCLUDEDIR}/bsnmp -I${.CURDIR} + +.include diff --git a/usr.sbin/bsnmpd/modules/snmp_netgraph/BEGEMOT-NETGRAPH.txt b/usr.sbin/bsnmpd/modules/snmp_netgraph/BEGEMOT-NETGRAPH.txt new file mode 100644 index 00000000000..d49216a1a41 --- /dev/null +++ b/usr.sbin/bsnmpd/modules/snmp_netgraph/BEGEMOT-NETGRAPH.txt @@ -0,0 +1,398 @@ +-- +-- Copyright (c) 2001-2003 +-- Fraunhofer Institute for Open Communication Systems (FhG Fokus). +-- All rights reserved. +-- +-- Author: Harti Brandt +-- +-- 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. +-- +-- 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. +-- +-- $FreeBSD$ +-- +-- Private MIB for netgraph part of Begemot SNMP daemon. +-- +BEGEMOT-NETGRAPH-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, Counter32, Unsigned32 + FROM SNMPv2-SMI + TEXTUAL-CONVENTION, TruthValue + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP + FROM SNMPv2-CONF + begemot + FROM BEGEMOT-MIB; + +begemotNg MODULE-IDENTITY + LAST-UPDATED "200201310000Z" + 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 for the NetGraph access module for SNMP." + ::= { begemot 2 } + +begemotNgObjects OBJECT IDENTIFIER ::= { begemotNg 1 } + +-- -------------------------------------------------------------------------- + +NgTypeName ::= TEXTUAL-CONVENTION + DISPLAY-HINT "15a" + STATUS current + DESCRIPTION + "Name of a netgraph type." + SYNTAX OCTET STRING (SIZE(1..15)) + +NgNodeName ::= TEXTUAL-CONVENTION + DISPLAY-HINT "15a" + STATUS current + DESCRIPTION + "Name of a netgraph node." + SYNTAX OCTET STRING (SIZE(1..15)) + +NgNodeNameOrEmpty ::= TEXTUAL-CONVENTION + DISPLAY-HINT "15a" + STATUS current + DESCRIPTION + "Name of a netgraph node." + SYNTAX OCTET STRING (SIZE(0..15)) + +NgHookName ::= TEXTUAL-CONVENTION + DISPLAY-HINT "15a" + STATUS current + DESCRIPTION + "Name of a netgraph hook." + SYNTAX OCTET STRING (SIZE(1..15)) + +NgNodeId ::= TEXTUAL-CONVENTION + DISPLAY-HINT "x" + STATUS current + DESCRIPTION + "Node identifier." + SYNTAX Unsigned32 (1..4294967295) + +NgNodeIdOrZero ::= TEXTUAL-CONVENTION + DISPLAY-HINT "x" + STATUS current + DESCRIPTION + "Node identifier or 0 for 'no-node'." + SYNTAX Unsigned32 (0..4294967295) + +-- -------------------------------------------------------------------------- +-- +-- Configuration parameters +-- +begemotNgConfig OBJECT IDENTIFIER ::= { begemotNgObjects 1 } + +begemotNgControlNodeName OBJECT-TYPE + SYNTAX NgNodeName + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The name of the netgraph node of this daemon. The name is + writeable during initialisation. If the name is set from + the empty string to the non-empty string, the netgraph socket + is created. Once set it cannot be changed." + ::= { begemotNgConfig 1 } + +begemotNgResBufSiz OBJECT-TYPE + SYNTAX INTEGER (1024..65536) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The size of the receive buffers for netgraph messages." + DEFVAL { 20000 } + ::= { begemotNgConfig 2 } + +begemotNgTimeout OBJECT-TYPE + SYNTAX INTEGER (10..10000) + UNITS "milliseconds" + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The maximum time to wait for a response to a netgraph message." + DEFVAL { 1000 } + ::= { begemotNgConfig 3 } + +begemotNgDebugLevel OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The netgraph library debug level. This should be set only + if the daemon is run with a terminal attached." + DEFVAL { 0 } + ::= { begemotNgConfig 4 } + +-- -------------------------------------------------------------------------- +-- +-- The STATISTICS Group +-- +begemotNgStats OBJECT IDENTIFIER ::= { begemotNgObjects 2 } + +begemotNgNoMems OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of times a memory allocation has failed for buffers + or the message queue." + ::= { begemotNgStats 1 } + +begemotNgMsgReadErrs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of times reading a netgraph message has failed." + ::= { begemotNgStats 2 } + +begemotNgTooLargeMsgs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of times a netgraph message was too large for + the buffer. Try increasing begemotNgResBufSiz if + this happens." + ::= { begemotNgStats 3 } + +begemotNgDataReadErrs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of times reading a netgraph data message has failed." + ::= { begemotNgStats 4 } + +begemotNgTooLargeDatas OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of times a netgraph data message was too large. + You need to increase begemotNgResBufSiz." + ::= { begemotNgStats 5 } + +-- ----------------------------------------------------- +-- +-- The NODE table +-- +begemotNgTypeTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotNgTypeEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table containing information about all netgraph node types." + ::= { begemotNgObjects 3 } + +begemotNgTypeEntry OBJECT-TYPE + SYNTAX BegemotNgTypeEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Table entry that describes one netgraph node." + INDEX { begemotNgTypeName } + ::= { begemotNgTypeTable 1 } + +BegemotNgTypeEntry ::= SEQUENCE { + begemotNgTypeName NgTypeName, + begemotNgTypeStatus INTEGER +} + +begemotNgTypeName OBJECT-TYPE + SYNTAX NgTypeName + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The name of the type. Used as index." + ::= { begemotNgTypeEntry 1 } + +begemotNgTypeStatus OBJECT-TYPE + SYNTAX INTEGER { loaded(1), unloaded(2) } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "If loaded then the node type is available. A type can be load + by setting this field to loaded. It is unload if the field is + set to unloaded. Note, that a type cannot be unloaded if it + is compiled into the kernel or has nodes of this type. The name + of the file containing the type implementation is constructed by + prepending ng_ to the type name." + ::= { begemotNgTypeEntry 2 } + +-- +-- Node table +-- +begemotNgNodeTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotNgNodeEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table containing information about all netgraph nodes." + ::= { begemotNgObjects 4 } + +begemotNgNodeEntry OBJECT-TYPE + SYNTAX BegemotNgNodeEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Table entry that describes one netgraph node." + INDEX { begemotNgNodeId } + ::= { begemotNgNodeTable 1 } + +BegemotNgNodeEntry ::= SEQUENCE { + begemotNgNodeId NgNodeId, + begemotNgNodeStatus INTEGER, + begemotNgNodeName NgNodeNameOrEmpty, + begemotNgNodeType NgTypeName, + begemotNgNodeHooks Unsigned32 +} + +begemotNgNodeId OBJECT-TYPE + SYNTAX NgNodeId + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The 32bit node id of this node. 0 is an illegal value." + ::= { begemotNgNodeEntry 1 } + +begemotNgNodeStatus OBJECT-TYPE + SYNTAX INTEGER { valid(1), invalid(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Indicates whether the node exists or not." + ::= { begemotNgNodeEntry 2 } + +begemotNgNodeName OBJECT-TYPE + SYNTAX NgNodeNameOrEmpty + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Name of the node (if any)." + ::= { begemotNgNodeEntry 3 } + +begemotNgNodeType OBJECT-TYPE + SYNTAX NgTypeName + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Type name of the node." + ::= { begemotNgNodeEntry 4 } + +begemotNgNodeHooks OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of hooks on this node." + ::= { begemotNgNodeEntry 5 } + +-- +-- Hook table +-- +begemotNgHookTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotNgHookEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table containing information about all netgraph hooks." + ::= { begemotNgObjects 5 } + +begemotNgHookEntry OBJECT-TYPE + SYNTAX BegemotNgHookEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Table entry that describes one netgraph node." + INDEX { begemotNgHookNodeId, begemotNgHookHook } + ::= { begemotNgHookTable 1 } + +BegemotNgHookEntry ::= SEQUENCE { + begemotNgHookNodeId NgNodeId, + begemotNgHookHook NgHookName, + begemotNgHookStatus INTEGER, + begemotNgHookPeerNodeId NgNodeId, + begemotNgHookPeerHook NgHookName, + begemotNgHookPeerType NgTypeName +} + +begemotNgHookNodeId OBJECT-TYPE + SYNTAX NgNodeId + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The 32bit node id of this node." + ::= { begemotNgHookEntry 1 } + +begemotNgHookHook OBJECT-TYPE + SYNTAX NgHookName + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Name of the hook." + ::= { begemotNgHookEntry 2 } + +begemotNgHookStatus OBJECT-TYPE + SYNTAX INTEGER { valid(1), invalid(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Indicates whether the hook exists or not." + ::= { begemotNgHookEntry 3 } + +begemotNgHookPeerNodeId OBJECT-TYPE + SYNTAX NgNodeId + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The 32bit node id of the peer node of this hook." + ::= { begemotNgHookEntry 4 } + +begemotNgHookPeerHook OBJECT-TYPE + SYNTAX NgHookName + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Name of the peer hook." + ::= { begemotNgHookEntry 5 } + +begemotNgHookPeerType OBJECT-TYPE + SYNTAX NgTypeName + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Name of the peer type." + ::= { begemotNgHookEntry 6 } + +END diff --git a/usr.sbin/bsnmpd/modules/snmp_netgraph/Makefile b/usr.sbin/bsnmpd/modules/snmp_netgraph/Makefile new file mode 100644 index 00000000000..6ccdf5f40f6 --- /dev/null +++ b/usr.sbin/bsnmpd/modules/snmp_netgraph/Makefile @@ -0,0 +1,15 @@ +# $FreeBSD$ +# +# Author: Harti Brandt + +MOD= netgraph +SRCS= snmp_netgraph.c +MAN= snmp_netgraph.3 + +MIBS= BEGEMOT-NETGRAPH.txt +DEFS= ${MOD}_tree.def +INCS= snmp_${MOD}.h + +CFLAGS+= -I${INCLUDEDIR}/bsnmp -I${.CURDIR} + +.include diff --git a/usr.sbin/bsnmpd/modules/snmp_netgraph/netgraph_tree.def b/usr.sbin/bsnmpd/modules/snmp_netgraph/netgraph_tree.def new file mode 100644 index 00000000000..eff59ff15c7 --- /dev/null +++ b/usr.sbin/bsnmpd/modules/snmp_netgraph/netgraph_tree.def @@ -0,0 +1,78 @@ +# +# Copyright (c) 2001-2003 +# Fraunhofer Institute for Open Communication Systems (FhG Fokus). +# All rights reserved. +# +# Author: Harti Brandt +# +# 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. +# +# 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. +# +# $FreeBSD$ +# +# Definition of the tree implemented by snmp_netgraph. +# +(1 internet + (4 private + (1 enterprises + (12325 fokus + (1 begemot + (2 begemotNg + (1 begemotNgObjects + (1 begemotNgConfig + (1 begemotNgControlNodeName OCTETSTRING op_ng_config GET SET) + (2 begemotNgResBufSiz INTEGER op_ng_config GET SET) + (3 begemotNgTimeout INTEGER op_ng_config GET SET) + (4 begemotNgDebugLevel UNSIGNED32 op_ng_config GET SET) + ) +# Change definition of stats array if you change StatsGroup + (2 begemotNgStats + (1 begemotNgNoMems COUNTER op_ng_stats GET) + (2 begemotNgMsgReadErrs COUNTER op_ng_stats GET) + (3 begemotNgTooLargeMsgs COUNTER op_ng_stats GET) + (4 begemotNgDataReadErrs COUNTER op_ng_stats GET) + (5 begemotNgTooLargeDatas COUNTER op_ng_stats GET) + ) + (3 begemotNgTypeTable + (1 begemotNgTypeEntry : OCTETSTRING op_ng_type + (1 begemotNgTypeName OCTETSTRING) + (2 begemotNgTypeStatus INTEGER GET SET) + )) + (4 begemotNgNodeTable + (1 begemotNgNodeEntry : INTEGER op_ng_node + (1 begemotNgNodeId UNSIGNED32) + (2 begemotNgNodeStatus INTEGER GET) + (3 begemotNgNodeName OCTETSTRING GET) + (4 begemotNgNodeType OCTETSTRING GET) + (5 begemotNgNodeHooks UNSIGNED32 GET) + )) + (5 begemotNgHookTable + (1 begemotNgHookEntry : UNSIGNED32 OCTETSTRING op_ng_hook + (1 begemotNgHookNodeId UNSIGNED32) + (2 begemotNgHookHook OCTETSTRING) + (3 begemotNgHookStatus INTEGER GET) + (4 begemotNgHookPeerNodeId UNSIGNED32 GET) + (5 begemotNgHookPeerHook OCTETSTRING GET) + (6 begemotNgHookPeerType OCTETSTRING GET) + )) + )) +))))) diff --git a/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.3 b/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.3 new file mode 100644 index 00000000000..fdd55faf1fe --- /dev/null +++ b/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.3 @@ -0,0 +1,416 @@ +.\" +.\" Copyright (c) 2001-2003 +.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus). +.\" All rights reserved. +.\" +.\" Author: Harti Brandt +.\" +.\" 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. +.\" +.\" 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. +.\" +.\" $FreeBSD$ +.\" +.Dd October 7, 2003 +.Dt snmp_netgraph 3 +.Os +.Sh NAME +.Nm snmp_node , +.Nm snmp_nodename , +.Nm ng_cookie_f , +.Nm ng_hook_f , +.Nm ng_register_cookie , +.Nm ng_unregister_cookie , +.Nm ng_register_hook , +.Nm ng_unregister_hook , +.Nm ng_unregister_module , +.Nm ng_output , +.Nm ng_output_node , +.Nm ng_output_id , +.Nm ng_dialog , +.Nm ng_dialog_node , +.Nm ng_dialog_id , +.Nm ng_send_data , +.Nm ng_mkpeer_id , +.Nm ng_connect_node , +.Nm ng_connect_id , +.Nm ng_connect2_id , +.Nm ng_connect2_tee_id , +.Nm ng_rmhook , +.Nm ng_rmhook_id , +.Nm ng_rmhook_tee_id , +.Nm ng_shutdown_id , +.Nm ng_next_node_id , +.Nm ng_node_id , +.Nm ng_node_id_node , +.Nm ng_node_name , +.Nm ng_node_type , +.Nm ng_peer_hook_id +.Nd "netgraph module for snmpd. +.Sh LIBRARY +.Pq begemotSnmpdModulePath."netgraph" = "/usr/lib/snmp_netgraph.so" +.Sh SYNOPSIS +.In bsnmp/snmpmod.h +.In bsnmp/snmp_netgraph.h +.Vt extern ng_ID_t snmp_node ; +.Vt extern u_char *snmp_nodename ; +.Ft typedef void +.Fn ng_cookie_f "const struct ng_mesg *mesg" "const char *path" "ng_ID_t id" "void *uarg" +.Ft typedef void +.Fn ng_hook_f "const char *hook" "const u_char *mesg" "size_t len" "void *uarg" +.Ft void * +.Fn ng_register_cookie "const struct lmodule *mod" "u_int32_t cookie" "ng_ID_t id" "ng_cookie_f *func" "void *uarg" +.Ft void +.Fn ng_unregister_cookie "void *reg" +.Ft void * +.Fn ng_register_hook "const struct lmodule *mod" "const char *hook" "ng_hook_f *func" "void *uarg" +.Ft void +.Fn ng_unregister_hook "void *reg" +.Ft void +.Fn ng_unregister_module "const struct lmodule *mod" +.Ft int +.Fn ng_output "const char *path" "u_int cookie" "u_int opcode" "const void *arg" "size_t arglen" +.Ft int +.Fn ng_output_node "const char *node" "u_int cookie" "u_int opcode" "const void *arg" "size_t arglen" " +.Ft int +.Fn ng_output_id "ng_ID_t node" "u_int cookie" "u_int opcode" "const void *arg" "size_t arglen" " +.Ft struct ng_mesg * +.Fn ng_dialog "const char *path" "u_int cookie" "u_int opcode" "const void *arg" "size_t arglen" +.Ft struct ng_mesg * +.Fn ng_dialog_node "const char *node" "u_int cookie" "u_int opcode" "const void *arg" "size_t arglen" " +.Ft struct ng_mesg * +.Fn ng_dialog_id "ng_ID_t id" "u_int cookie" "u_int opcode" "const void *arg" "size_t arglen" " +.Ft int +.Fn ng_send_data "const char *hook" "const void *sndbuf" "size_t sndlen" +.Ft ng_ID_t +.Fn ng_mkpeer_id "ng_ID_t id" "const char *name" "const char *type" "const char *hook" "const char *peerhook" +.Ft int +.Fn ng_connect_node "const char *node" "const char *ourhook" "const char *peerhook" +.Ft int +.Fn ng_connect_id "ng_ID_t id" "const char *ourhook" "const char *peerhook" +.Ft int +.Fn ng_connect2_id "ng_ID_t id" "ng_ID_t peer" "const char *ourhook" "const char *peerhook" +.Ft int +.Fn ng_connect2_tee_id "ng_ID_t id" "ng_ID_t peer" "const char *ourhook" "const char *peerhook" +.Ft int +.Fn ng_rmhook "const char *ourhook" +.Ft int +.Fn ng_rmhook_id "ng_ID_t id" "const char *hook" +.Ft int +.Fn ng_rmhook_tee_id "ng_ID_t id" "const char *hook" +.Ft int +.Fn ng_shutdown_id "ng_ID_t id" +.Ft ng_ID_t +.Fn ng_next_node_id "ng_ID_t node, const char *type, const char *hook); +.Ft ng_ID_t +.Fn ng_node_id "const char *path" +.Ft ng_ID_t +.Fn ng_node_id_node "const char *node" +.Ft ng_ID_t +.Fn ng_node_name "ng_ID_t id, char *name" +.Ft ng_ID_t +.Fn ng_node_type "ng_ID_t id, char *type" +.Ft int +.Fn ng_peer_hook_id "ng_ID_t id" "const char *hook" "char *peerhook" +.Sh DESCRIPTION +The +.Nm snmp_netgraph +module implements a number of tables and scalars that enable remote access to +the netgraph subsystem. It also exports a number of global variables and +functions, that allow other modules to easily use the netgraph system. +.Pp +If upon start up of the module the variable +.Va begemotNgControlNodeName +is not empty the module opens a netgraph socket and names that socket node. +If the variable is empty, the socket is created, as soon as the variable is +written with a non-empty name. The socket can be closed by writing an empty +string to the variable. The socket itself and its name are available in +.Va snmp_node +and +.Va snmp_nodename . +.Ss SENDING AND RECEIVING MESSAGES AND DATA +There are three functions for sending control message: +.Bl -tag -width ".It Fn ng_output_node" +.It Fn ng_output +sends a control message along the given +.Fa path . +.It Fn ng_output_node +sends a control message to the node with name +.Fa node +and +.It Fn ng_output_id +sends a control message to the node with node id +.Fa id . +.El +.Pp +Each of these functions takes the following arguments: +.Bl -tag -width ".It Fa cookie" +.It Fa cookie +is the node specific command cookie, +.It Fa opcode +is the node specific code for the operation to performa, +.It Fa arg +is a pointer to the message itself. This message must start with a +.Vt struct ng_mesg . +.It Fa arglen +is the overall length of the message (header plus arguments). +.El +The functions return the message id that can be used to match incoming responses +or -1 if an error occurs. +.Pp +Another class of functions is used to send a control message and to wait for +a matching response. Note, that this operation blocks the daemon, so use it +only if you are sure that the response will happen. There is a maximum timeout +that is configurable in the MIB variable +.Va begemotNgTimeout . +Other messages arriving while the functions are waiting for the response are +queued and delivered on the next call to the module's idle function. +.Bl -tag -width ".It Fn ng_output_node" +.It Fn ng_dialog +sends a control message along the given +.Fa path +and waits for a matching response. +.It Fn ng_dialog_node +sends a control message to the node with name +.Fa node +and waits for a matching response. +.It Fn ng_dialog_id +sends a control message to the node with id +.Fa id +and waits for a matching response. +.El +.Pp +All three functions take the same arguments as the +.Fn ng_output* +functions. The functions return the reponse message in a buffer allocated by +.Xr malloc 3 +or NULL in case of an error. The maximum size of the response buffer can be +configured in the variable +.Va begemotNgResBufSiz . +.Pp +A data message can be send with the function +.Fn ng_send_data . +This function takes the name of the +.Va snmp_node Ns 's +hook through which to send the data, a pointer to the message buffer and +the size of the message. It returns -1 if an error happens. +.Ss ASYNCHRONOUS CONTROL AND DATA MESSAGES +A module can register functions to asynchronuosly receive control and data +message. +.Pp +The function +.Fn ng_register_cookie +registers a control message receive function. If a control message is +received, that is not consumed by the dialog functions, the list of registerred +control message receive functions is scanned. If the cookie in the received +message is the same as the +.Fa cookie +argument to the +.Fn ng_register_cookie +call and the +.Fn +.Fa id +argument to the +.Fn ng_register_cookie +call was either 0 or equals the node id which sent the control message, the +handler function +.Fa func +is called with a pointer to the received message, the hook on which the +message was received (or NULL if it was received not on a hook), the id +of the sender's node and the +.Fa uarg +argument of the registration call. The handler function should not modify +the contents of the message, because more than one function may be registered +to the same cookie and node id. +.Pp +A control message registration can be undone by calling +.Fn ng_unregister_cookie +with the return value of the registration call. +If an error occures while registering, +.Fn ng_register_cookie +returns NULL. +.Pp +A module can call +.Fn ng_register_hook +to register a callback for data messages on one of the +.Va snmp_node Ns 's +hooks. If a data message is received on that hook, the callback function +.Fa func +is called with the hook name, a pointer to the data message, the size of +the message and the argument +.Fa uarg +to the registration function. The message should be treated as read-only. +A data message registration can be undone by calling +.Fn ng_unregister_hook +with the return value of the registration call. +If an error occures while registering, +.Fn ng_register_hook +returns NULL. +.Pp +The function +.Fn ng_unregister_module +removes all control and data registrations for that module. +.Ss FINDING NODES AND NODE CHARACTERISTICS +.Pp +The function +.Fn ng_node_id +returns the id of the node addressed by +.Fa path +or 0 if the node does not exists. +.Pp +The function +.Fn ng_node_id_node +returns the id of the node with name +.Fa node +or 0 if the node does not exist. +.Pp +The function +.Fn ng_node_node +retrieves the name of the node with id +.Fa id +and writes it to the buffer pointed to by +.Fa name . +This buffer should be at least +.Li NG_NODELEN ++ 1 long. The function returns the node id or 0 if the +node is not found +.Pp +The function +.Fn ng_node_type +retrieves the name of the node with id +.Fa id +and writes it to the buffer pointed to by +.Fa type . +This buffer should be at least +.Li NG_TYPELEN ++ 1 long. The function returns the node id or 0 if the +node is not found. +.Pp +The function +.Fn ng_peer_hook_id +writes the name of the peer hook of the hook +.Fa hook +on the node with +.Fa id +to the buffer pointed to by +.Fa peer_hook . +The buffer should be at least +.Li NG_HOOKLEN ++ 1 long. The function returns 0 if the node and the hook is found, -1 +otherwise. The function skips intermediate tee nodes (see +.Xr ng_tee 4 ). +.Pp +The function +.Fn ng_next_node_id +returns the node id of the peer node that is on the other side of hook +.Fa hook +of node +.Fa id . +If +.Fa type +is not NULL, the function checks, that the peer node's type is +.Fa type . +The function skips intermediate tee nodes (see +.Xr ng_tee 4 ). +It returns the node id of the peer node or 0 if an error occurres or the +types do not match. +.Ss CHANGING THE GRAPH +A number of functions can be used to create or destroy nodes and hooks. +.Pp +The function +.Fn ng_mkpeer_id +creates a new node of type +.Fa type +who's hook +.Fa peerhook +will be connected to +.Fa hook +of node +.Fa id . +If +.Fa name +is not NULL the new node is named with this name. The function returns +The node id of the new node or 0 if an error happens. +.Pp +The functions +.Fn ng_connect_node +and +.Fn ng_connect_id +make a new hook connecting +.Fa ourhook +of the modules socket node +.Va snmp_node +to +.Fa peerhook +of the node identified by id +.Fa id +or name +.Fa node . +The functions return 0 on success or -1 otherwise. +.Pp +The function +.Fn ng_connect2_id +connects hook +.Fa ourhook +of the node with id +.Fa id +to hook +.Fa peerhook +of the node with id +.Fa peer . +The functions return 0 on success or -1 otherwise. +The function +.Fn ng_connect2_tee_id does the same as +.Fn ng_connect2_id +except, that it puts an unnamed tee node between the two nodes. +.Pp +The function +.Fn ng_rmhook +removes hook +.Fa hook +on the module's +.Va snmp_node . +The function +.Fn ng_rmhook_id +removes hook +.Fa hook +on the node with id +.Fa id . +The function +.Fn ng_rmhook_tee_id +additionally shuts down all tee nodes between the node and the first non-tee +peer. +.Pp +The function +.Fn ng_shutdown_id +destroys the given node. +.Sh FILES +.Bl -tag -width "XXXXXXXXX" +.It Pa /usr/share/bsnmp/defs/netgraph_tree.def +The description of the MIB tree implemented by +.Nm . +.It Pa /usr/share/bsnmp/mibs/BEGEMOT-NETGRAPH.txt +This is the MIB that is implemented by this module. +.Sh SEE ALSO +.Xr snmpmod 3 , +.Xr gensnmptree 1 +.Sh AUTHORS +.An Hartmut Brandt Aq harti@freebsd.org diff --git a/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.c b/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.c new file mode 100644 index 00000000000..4a70834ebab --- /dev/null +++ b/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.c @@ -0,0 +1,1691 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * 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. + * + * 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. + * + * $FreeBSD$ + * + * Netgraph interface for SNMPd. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "snmpmod.h" +#include "snmp_netgraph.h" +#include "netgraph_tree.h" +#include "netgraph_oid.h" + +/* maximum message size */ +#define RESBUFSIZ 20000 + +/* default node name */ +#define NODENAME "NgSnmpd" + +/* my node Id */ +ng_ID_t snmp_node; +u_char *snmp_nodename; + +/* the Object Resource registration index */ +static u_int reg_index; +static const struct asn_oid oid_begemotNg = OIDX_begemotNg; + +/* configuration */ +/* this must be smaller than int32_t because the functions in libnetgraph + * falsely return an int */ +static size_t resbufsiz = RESBUFSIZ; +static u_int timeout = 1000; +static u_int debug_level; + +/* number of microseconds per clock tick */ +static struct clockinfo clockinfo; + +/* Csock buffers. Communication on the csock is asynchronuous. This means + * if we wait for a specific response, we may get other messages. Put these + * into a queue and execute them when we are idle. */ +struct csock_buf { + STAILQ_ENTRY(csock_buf) link; + struct ng_mesg *mesg; + char path[NG_PATHLEN + 1]; +}; +static STAILQ_HEAD(, csock_buf) csock_bufs = + STAILQ_HEAD_INITIALIZER(csock_bufs); + +/* + * We dispatch unsolicieted messages by node cookies and ids. + * So we must keep a list of hook names and dispatch functions. + */ +struct msgreg { + u_int32_t cookie; + ng_ID_t id; + ng_cookie_f *func; + void *arg; + const struct lmodule *mod; + SLIST_ENTRY(msgreg) link; +}; +static SLIST_HEAD(, msgreg) msgreg_list = + SLIST_HEAD_INITIALIZER(msgreg_list); + +/* + * Data messages are dispatched by hook names. + */ +struct datareg { + char hook[NG_HOOKLEN + 1]; + ng_hook_f *func; + void *arg; + const struct lmodule *mod; + SLIST_ENTRY(datareg) link; +}; +static SLIST_HEAD(, datareg) datareg_list = + SLIST_HEAD_INITIALIZER(datareg_list); + +/* the netgraph sockets */ +static int csock, dsock; +static void *csock_fd, *dsock_fd; + +/* our module handle */ +static struct lmodule *module; + +/* statistics */ +static u_int32_t stats[LEAF_begemotNgTooLargeDatas+1]; + +/* netgraph type list */ +struct ngtype { + char name[NG_TYPELEN + 1]; + struct asn_oid index; + TAILQ_ENTRY(ngtype) link; +}; +TAILQ_HEAD(ngtype_list, ngtype); + +static struct ngtype_list ngtype_list; +static u_int32_t ngtype_tick; + + +/* + * Register a function to receive unsolicited messages + */ +void * +ng_register_cookie(const struct lmodule *mod, u_int32_t cookie, ng_ID_t id, + ng_cookie_f *func, void *arg) +{ + struct msgreg *d; + + if ((d = malloc(sizeof(*d))) == NULL) + return (NULL); + + d->cookie = cookie; + d->id = id; + d->func = func; + d->arg = arg; + d->mod = mod; + + SLIST_INSERT_HEAD(&msgreg_list, d, link); + + return (d); +} + +/* + * Remove a registration. + */ +void +ng_unregister_cookie(void *dd) +{ + struct msgreg *d = dd; + + SLIST_REMOVE(&msgreg_list, d, msgreg, link); + free(d); +} + +/* + * Register a function for hook data. + */ +void * +ng_register_hook(const struct lmodule *mod, const char *hook, + ng_hook_f *func, void *arg) +{ + struct datareg *d; + + if ((d = malloc(sizeof(*d))) == NULL) + return (NULL); + + strcpy(d->hook, hook); + d->func = func; + d->arg = arg; + d->mod = mod; + + SLIST_INSERT_HEAD(&datareg_list, d, link); + + return (d); +} + +/* + * Unregister a hook function + */ +void +ng_unregister_hook(void *dd) +{ + struct datareg *d = dd; + + SLIST_REMOVE(&datareg_list, d, datareg, link); + free(d); +} + +/* + * Unregister all hooks and cookies for that module. Note: doesn't disconnect + * any hooks! + */ +void +ng_unregister_module(const struct lmodule *mod) +{ + struct msgreg *m, *m1; + struct datareg *d, *d1; + + m = SLIST_FIRST(&msgreg_list); + while (m != NULL) { + m1 = SLIST_NEXT(m, link); + if (m->mod == mod) { + SLIST_REMOVE(&msgreg_list, m, msgreg, link); + free(m); + } + m = m1; + } + + d = SLIST_FIRST(&datareg_list); + while (d != NULL) { + d1 = SLIST_NEXT(d, link); + if (d->mod == mod) { + SLIST_REMOVE(&datareg_list, d, datareg, link); + free(d); + } + d = d1; + } +} + +/* + * Dispatch a message to the correct module and delete it. More than one + * module can get a message. + */ +static void +csock_handle(struct ng_mesg *mesg, const char *path) +{ + struct msgreg *d, *d1; + u_int id; + int len; + + if (sscanf(path, "[%x]:%n", &id, &len) != 1 || + (u_int)len != strlen(path)) { + syslog(LOG_ERR, "cannot parse message path '%s'", path); + id = 0; + } + + d = SLIST_FIRST(&msgreg_list); + while (d != NULL) { + d1 = SLIST_NEXT(d, link); + if (d->cookie == mesg->header.typecookie && + (d->id == 0 || d->id == id || id == 0)) + (*d->func)(mesg, path, id, d->arg); + d = d1; + } + free(mesg); +} + +/* + * Input from the control socket. + */ +static struct ng_mesg * +csock_read(char *path) +{ + struct ng_mesg *mesg; + int ret, err; + + if ((mesg = malloc(resbufsiz + 1)) == NULL) { + stats[LEAF_begemotNgNoMems]++; + syslog(LOG_CRIT, "out of memory"); + errno = ENOMEM; + return (NULL); + } + if ((ret = NgRecvMsg(csock, mesg, resbufsiz + 1, path)) < 0) { + err = errno; + free(mesg); + if (errno == EWOULDBLOCK) { + errno = err; + return (NULL); + } + stats[LEAF_begemotNgMsgReadErrs]++; + syslog(LOG_WARNING, "read from csock: %m"); + errno = err; + return (NULL); + } + if (ret == 0) { + syslog(LOG_DEBUG, "node closed -- exiting"); + exit(0); + } + if ((size_t)ret > resbufsiz) { + stats[LEAF_begemotNgTooLargeMsgs]++; + syslog(LOG_WARNING, "ng message too large"); + free(mesg); + errno = EFBIG; + return (NULL); + } + return (mesg); +} + +static void +csock_input(int fd __unused, void *udata __unused) +{ + struct ng_mesg *mesg; + char path[NG_PATHLEN + 1]; + + if ((mesg = csock_read(path)) == NULL) + return; + + csock_handle(mesg, path); +} + +/* + * Write a message to a node. + */ +int +ng_output(const char *path, u_int cookie, u_int opcode, + const void *arg, size_t arglen) +{ + return (NgSendMsg(csock, path, (int)cookie, (int)opcode, arg, arglen)); +} +int +ng_output_node(const char *node, u_int cookie, u_int opcode, + const void *arg, size_t arglen) +{ + char path[NG_PATHLEN + 1]; + + sprintf(path, "%s:", node); + return (ng_output(path, cookie, opcode, arg, arglen)); +} +int +ng_output_id(ng_ID_t node, u_int cookie, u_int opcode, + const void *arg, size_t arglen) +{ + char path[NG_PATHLEN + 1]; + + sprintf(path, "[%x]:", node); + return (ng_output(path, cookie, opcode, arg, arglen)); +} + + + +/* + * Execute a synchronuous dialog with the csock. All message we receive, that + * do not match our request, are queue until the next call to the IDLE function. + */ +struct ng_mesg * +ng_dialog(const char *path, u_int cookie, u_int opcode, + const void *arg, size_t arglen) +{ + int token, err; + struct ng_mesg *mesg; + char rpath[NG_PATHLEN + 1]; + struct csock_buf *b; + struct timeval end, tv; + + if ((token = ng_output(path, cookie, opcode, arg, arglen)) < 0) + return (NULL); + + if (csock_fd) + fd_suspend(csock_fd); + + gettimeofday(&end, NULL); + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + timeradd(&end, &tv, &end); + for (;;) { + mesg = NULL; + gettimeofday(&tv, NULL); + if (timercmp(&tv, &end, >=)) { + block: + syslog(LOG_WARNING, "no response for request %u/%u", + cookie, opcode); + errno = EWOULDBLOCK; + break; + } + timersub(&end, &tv, &tv); + if (tv.tv_sec == 0 && tv.tv_usec < clockinfo.tick) + goto block; + + if (setsockopt(csock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) + syslog(LOG_WARNING, "setsockopt(SO_RCVTIMEO): %m"); + if ((mesg = csock_read(rpath)) == NULL) { + if (errno == EWOULDBLOCK) + continue; + break; + } + if (mesg->header.token == (u_int)token) + break; + if ((b = malloc(sizeof(*b))) == NULL) { + stats[LEAF_begemotNgNoMems]++; + syslog(LOG_ERR, "out of memory"); + free(mesg); + continue; + } + b->mesg = mesg; + strcpy(b->path, rpath); + STAILQ_INSERT_TAIL(&csock_bufs, b, link); + } + + tv.tv_sec = 0; + tv.tv_usec = 0; + if (setsockopt(csock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) + syslog(LOG_WARNING, "setsockopt(SO_RCVTIMEO,0): %m"); + + if (csock_fd) { + err = errno; + fd_resume(csock_fd); + errno = err; + } + + return (mesg); +} +struct ng_mesg * +ng_dialog_node(const char *node, u_int cookie, u_int opcode, + const void *arg, size_t arglen) +{ + char path[NG_PATHLEN + 1]; + + sprintf(path, "%s:", node); + return (ng_dialog(path, cookie, opcode, arg, arglen)); +} +struct ng_mesg * +ng_dialog_id(ng_ID_t id, u_int cookie, u_int opcode, + const void *arg, size_t arglen) +{ + char path[NG_PATHLEN + 1]; + + sprintf(path, "[%x]:", id); + return (ng_dialog(path, cookie, opcode, arg, arglen)); +} + + +/* + * Send a data message to a given hook. + */ +int +ng_send_data(const char *hook, const void *sndbuf, size_t sndlen) +{ + return (NgSendData(dsock, hook, sndbuf, sndlen)); +} + +/* + * Input from a data socket. Dispatch to the function for that hook. + */ +static void +dsock_input(int fd __unused, void *udata __unused) +{ + u_char *resbuf, embuf[100]; + ssize_t len; + char hook[NG_HOOKLEN + 1]; + struct datareg *d, *d1; + + if ((resbuf = malloc(resbufsiz + 1)) == NULL) { + stats[LEAF_begemotNgNoMems]++; + syslog(LOG_CRIT, "out of memory"); + (void)NgRecvData(fd, embuf, sizeof(embuf), hook); + errno = ENOMEM; + return; + } + if ((len = NgRecvData(fd, resbuf, resbufsiz + 1, hook)) == -1) { + stats[LEAF_begemotNgDataReadErrs]++; + syslog(LOG_ERR, "reading message: %m"); + free(resbuf); + return; + } + if (len == 0) { + free(resbuf); + return; + } + if ((size_t)len == resbufsiz + 1) { + stats[LEAF_begemotNgTooLargeDatas]++; + syslog(LOG_WARNING, "message too long"); + free(resbuf); + return; + } + + /* + * Dispatch message. Maybe dispatched to more than one function. + */ + d = SLIST_FIRST(&datareg_list); + while (d != NULL) { + d1 = SLIST_NEXT(d, link); + if (strcmp(hook, d->hook) == 0) + (*d->func)(hook, resbuf, len, d->arg); + d = d1; + } + + free(resbuf); +} + +/* + * The SNMP daemon is about to wait for an event. Look whether we have + * netgraph messages waiting. If yes, drain the queue. + */ +static void +ng_idle(void) +{ + struct csock_buf *b; + + /* execute waiting csock_bufs */ + while ((b = STAILQ_FIRST(&csock_bufs)) != NULL) { + STAILQ_REMOVE_HEAD(&csock_bufs, link); + csock_handle(b->mesg, b->path); + free(b); + } +} + +/* + * Called when the module is loaded. Returning a non-zero value means, + * rejecting the initialisation. + * + * We make the netgraph socket. + */ +static int +ng_init(struct lmodule *mod, int argc, char *argv[]) +{ + int name[2]; + size_t len; + + module = mod; + + if (argc == 0) { + if ((snmp_nodename = malloc(strlen(NODENAME) + 1)) == NULL) + return (ENOMEM); + strcpy(snmp_nodename, NODENAME); + } else { + if ((snmp_nodename = malloc(NG_NODELEN + 1)) == NULL) + return (ENOMEM); + snprintf(snmp_nodename, NG_NODELEN + 1, "%s", argv[0]); + } + + /* fetch clockinfo (for the number of microseconds per tick) */ + name[0] = CTL_KERN; + name[1] = KERN_CLOCKRATE; + len = sizeof(clockinfo); + if (sysctl(name, 2, &clockinfo, &len, NULL, 0) == -1) + return (errno); + + TAILQ_INIT(&ngtype_list); + + return (0); +} + +/* + * Get the node Id/name/type of a node. + */ +ng_ID_t +ng_node_id(const char *path) +{ + struct ng_mesg *resp; + ng_ID_t id; + + if ((resp = ng_dialog(path, NGM_GENERIC_COOKIE, NGM_NODEINFO, + NULL, 0)) == NULL) + return (0); + id = ((struct nodeinfo *)(void *)resp->data)->id; + free(resp); + return (id); +} +ng_ID_t +ng_node_id_node(const char *node) +{ + struct ng_mesg *resp; + ng_ID_t id; + + if ((resp = ng_dialog_node(node, NGM_GENERIC_COOKIE, NGM_NODEINFO, + NULL, 0)) == NULL) + return (0); + id = ((struct nodeinfo *)(void *)resp->data)->id; + free(resp); + return (id); +} +ng_ID_t +ng_node_name(ng_ID_t id, char *name) +{ + struct ng_mesg *resp; + + if ((resp = ng_dialog_id(id, NGM_GENERIC_COOKIE, NGM_NODEINFO, + NULL, 0)) == NULL) + return (0); + strcpy(name, ((struct nodeinfo *)(void *)resp->data)->name); + free(resp); + return (id); + +} +ng_ID_t +ng_node_type(ng_ID_t id, char *type) +{ + struct ng_mesg *resp; + + if ((resp = ng_dialog_id(id, NGM_GENERIC_COOKIE, NGM_NODEINFO, + NULL, 0)) == NULL) + return (0); + strcpy(type, ((struct nodeinfo *)(void *)resp->data)->type); + free(resp); + return (id); +} + +/* + * Connect our node to some other node + */ +int +ng_connect_node(const char *node, const char *ourhook, const char *peerhook) +{ + struct ngm_connect conn; + + snprintf(conn.path, NG_PATHLEN + 1, "%s:", node); + snprintf(conn.ourhook, NG_HOOKLEN + 1, ourhook); + snprintf(conn.peerhook, NG_HOOKLEN + 1, peerhook); + return (NgSendMsg(csock, ".:", + NGM_GENERIC_COOKIE, NGM_CONNECT, &conn, sizeof(conn))); +} +int +ng_connect_id(ng_ID_t id, const char *ourhook, const char *peerhook) +{ + struct ngm_connect conn; + + snprintf(conn.path, NG_PATHLEN + 1, "[%x]:", id); + snprintf(conn.ourhook, NG_HOOKLEN + 1, ourhook); + snprintf(conn.peerhook, NG_HOOKLEN + 1, peerhook); + return (NgSendMsg(csock, ".:", + NGM_GENERIC_COOKIE, NGM_CONNECT, &conn, sizeof(conn))); +} + +int +ng_connect2_id(ng_ID_t id, ng_ID_t peer, const char *ourhook, + const char *peerhook) +{ + struct ngm_connect conn; + char path[NG_PATHLEN + 1]; + + snprintf(path, NG_PATHLEN + 1, "[%x]:", id); + + snprintf(conn.path, NG_PATHLEN + 1, "[%x]:", peer); + snprintf(conn.ourhook, NG_HOOKLEN + 1, ourhook); + snprintf(conn.peerhook, NG_HOOKLEN + 1, peerhook); + return (NgSendMsg(csock, path, + NGM_GENERIC_COOKIE, NGM_CONNECT, &conn, sizeof(conn))); +} + +int +ng_connect2_tee_id(ng_ID_t id, ng_ID_t peer, const char *ourhook, + const char *peerhook) +{ + struct ngm_connect conn; + char path[NG_PATHLEN + 1]; + ng_ID_t tee; + + if ((tee = ng_mkpeer_id(id, NULL, "tee", ourhook, "left")) == 0) + return (-1); + + snprintf(path, NG_PATHLEN + 1, "[%x]:", tee); + + snprintf(conn.path, NG_PATHLEN + 1, "[%x]:", peer); + snprintf(conn.ourhook, NG_HOOKLEN + 1, "right"); + snprintf(conn.peerhook, NG_HOOKLEN + 1, peerhook); + return (NgSendMsg(csock, path, + NGM_GENERIC_COOKIE, NGM_CONNECT, &conn, sizeof(conn))); +} + +/* + * Ensure that a node of type 'type' is connected to 'hook' of 'node' + * and return its node id. tee nodes between node and the target node + * are skipped. If the type is wrong, or the hook is a dead-end return 0. + * If type is NULL, it is not checked. + */ +static ng_ID_t +ng_next_node_id_internal(ng_ID_t node, const char *type, const char *hook, + int skip_tee) +{ + struct ng_mesg *resp; + struct hooklist *hooklist; + u_int i; + + if ((resp = ng_dialog_id(node, NGM_GENERIC_COOKIE, NGM_LISTHOOKS, + NULL, 0)) == NULL) { + syslog(LOG_ERR, "get hook list: %m"); + exit(1); + } + hooklist = (struct hooklist *)(void *)resp->data; + + for (i = 0; i < hooklist->nodeinfo.hooks; i++) + if (strcmp(hooklist->link[i].ourhook, hook) == 0) + break; + + if (i == hooklist->nodeinfo.hooks) { + free(resp); + return (0); + } + + node = hooklist->link[i].nodeinfo.id; + + if (skip_tee && strcmp(hooklist->link[i].nodeinfo.type, "tee") == 0) { + if (strcmp(hooklist->link[i].peerhook, "left") == 0) + node = ng_next_node_id(node, type, "right"); + else if (strcmp(hooklist->link[i].peerhook, "right") == 0) + node = ng_next_node_id(node, type, "left"); + else if (type != NULL && + strcmp(hooklist->link[i].nodeinfo.type, type) != 0) + node = 0; + + } else if (type != NULL && + strcmp(hooklist->link[i].nodeinfo.type, type) != 0) + node = 0; + + free(resp); + + return (node); +} + +/* + * Ensure that a node of type 'type' is connected to 'hook' of 'node' + * and return its node id. tee nodes between node and the target node + * are skipped. If the type is wrong, or the hook is a dead-end return 0. + * If type is NULL, it is not checked. + */ +ng_ID_t +ng_next_node_id(ng_ID_t node, const char *type, const char *hook) +{ + return (ng_next_node_id_internal(node, type, hook, 1)); +} + +ng_ID_t +ng_mkpeer_id(ng_ID_t id, const char *nodename, const char *type, + const char *hook, const char *peerhook) +{ + char path[NG_PATHLEN + 1]; + struct ngm_mkpeer mkpeer; + struct ngm_name name; + + strcpy(mkpeer.type, type); + strcpy(mkpeer.ourhook, hook); + strcpy(mkpeer.peerhook, peerhook); + + sprintf(path, "[%x]:", id); + if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, NGM_MKPEER, + &mkpeer, sizeof(mkpeer)) == -1) + return (0); + + if ((id = ng_next_node_id_internal(id, NULL, hook, 0)) == NULL) + return (0); + + if (nodename != NULL) { + strcpy(name.name, nodename); + sprintf(path, "[%x]:", id); + if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, NGM_NAME, + &name, sizeof(name)) == -1) + return (0); + } + return (id); +} + +/* + * SHutdown node + */ +int +ng_shutdown_id(ng_ID_t id) +{ + char path[NG_PATHLEN + 1]; + + sprintf(path, "[%x]:", id); + return (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, + NGM_SHUTDOWN, NULL, 0)); +} + +/* + * Disconnect one of our hooks + */ +int +ng_rmhook(const char *ourhook) +{ + struct ngm_rmhook rmhook; + + snprintf(rmhook.ourhook, NG_HOOKLEN + 1, "%s", ourhook); + return (NgSendMsg(csock, ".:", + NGM_GENERIC_COOKIE, NGM_RMHOOK, &rmhook, sizeof(rmhook))); +} + +/* + * Disconnect a hook of a node + */ +int +ng_rmhook_id(ng_ID_t id, const char *hook) +{ + struct ngm_rmhook rmhook; + char path[NG_PATHLEN + 1]; + + snprintf(rmhook.ourhook, NG_HOOKLEN + 1, "%s", hook); + sprintf(path, "[%x]:", id); + return (NgSendMsg(csock, path, + NGM_GENERIC_COOKIE, NGM_RMHOOK, &rmhook, sizeof(rmhook))); +} + +/* + * Disconnect a hook and shutdown all tee nodes that were connected to that + * hook. + */ +int +ng_rmhook_tee_id(ng_ID_t node, const char *hook) +{ + struct ng_mesg *resp; + struct hooklist *hooklist; + u_int i; + int first = 1; + ng_ID_t next_node; + const char *next_hook; + + again: + /* if we have just shutdown a tee node, which had no other hooks + * connected, the node id may already be wrong here. */ + if ((resp = ng_dialog_id(node, NGM_GENERIC_COOKIE, NGM_LISTHOOKS, + NULL, 0)) == NULL) + return (0); + + hooklist = (struct hooklist *)(void *)resp->data; + + for (i = 0; i < hooklist->nodeinfo.hooks; i++) + if (strcmp(hooklist->link[i].ourhook, hook) == 0) + break; + + if (i == hooklist->nodeinfo.hooks) { + free(resp); + return (0); + } + + next_node = 0; + next_hook = NULL; + if (strcmp(hooklist->link[i].nodeinfo.type, "tee") == 0) { + if (strcmp(hooklist->link[i].peerhook, "left") == 0) { + next_node = hooklist->link[i].nodeinfo.id; + next_hook = "right"; + } else if (strcmp(hooklist->link[i].peerhook, "right") == 0) { + next_node = hooklist->link[i].nodeinfo.id; + next_hook = "left"; + } + } + free(resp); + + if (first) { + ng_rmhook_id(node, hook); + first = 0; + } else { + ng_shutdown_id(node); + } + if ((node = next_node) == 0) + return (0); + hook = next_hook; + + goto again; +} + +/* + * Get the peer hook of a hook on a given node. Skip any tee nodes in between + */ +int +ng_peer_hook_id(ng_ID_t node, const char *hook, char *peerhook) +{ + struct ng_mesg *resp; + struct hooklist *hooklist; + u_int i; + int ret; + + if ((resp = ng_dialog_id(node, NGM_GENERIC_COOKIE, NGM_LISTHOOKS, + NULL, 0)) == NULL) { + syslog(LOG_ERR, "get hook list: %m"); + exit(1); + } + hooklist = (struct hooklist *)(void *)resp->data; + + for (i = 0; i < hooklist->nodeinfo.hooks; i++) + if (strcmp(hooklist->link[i].ourhook, hook) == 0) + break; + + if (i == hooklist->nodeinfo.hooks) { + free(resp); + return (-1); + } + + node = hooklist->link[i].nodeinfo.id; + + ret = 0; + if (strcmp(hooklist->link[i].nodeinfo.type, "tee") == 0) { + if (strcmp(hooklist->link[i].peerhook, "left") == 0) + ret = ng_peer_hook_id(node, "right", peerhook); + else if (strcmp(hooklist->link[i].peerhook, "right") == 0) + ret = ng_peer_hook_id(node, "left", peerhook); + else + strcpy(peerhook, hooklist->link[i].peerhook); + + } else + strcpy(peerhook, hooklist->link[i].peerhook); + + free(resp); + + return (ret); +} + + +/* + * Now the module is started. Select on the sockets, so that we can get + * unsolicited input. + */ +static void +ng_start(void) +{ + if (snmp_node == 0) { + if (NgMkSockNode(snmp_nodename, &csock, &dsock) < 0) { + syslog(LOG_ERR, "NgMkSockNode: %m"); + exit(1); + } + snmp_node = ng_node_id(".:"); + } + + if ((csock_fd = fd_select(csock, csock_input, NULL, module)) == NULL) { + syslog(LOG_ERR, "fd_select failed on csock: %m"); + return; + } + if ((dsock_fd = fd_select(dsock, dsock_input, NULL, module)) == NULL) { + syslog(LOG_ERR, "fd_select failed on dsock: %m"); + return; + } + + reg_index = or_register(&oid_begemotNg, + "The MIB for the NetGraph access module for SNMP.", module); + +} + +/* + * Called, when the module is to be unloaded after it was successfully loaded + */ +static int +ng_fini(void) +{ + struct ngtype *t; + + while ((t = TAILQ_FIRST(&ngtype_list)) != NULL) { + TAILQ_REMOVE(&ngtype_list, t, link); + free(t); + } + + if (csock_fd != NULL) + fd_deselect(csock_fd); + (void)close(csock); + + if (dsock_fd != NULL) + fd_deselect(dsock_fd); + (void)close(dsock); + + free(snmp_nodename); + + or_unregister(reg_index); + + return (0); +} + +const struct snmp_module config = { + "This module implements access to the netgraph sub-system", + ng_init, + ng_fini, + ng_idle, + NULL, + NULL, + ng_start, + NULL, + netgraph_ctree, + netgraph_CTREE_SIZE, + NULL +}; + +int +op_ng_config(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + int ret; + + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + /* + * Come here for GET, GETNEXT and COMMIT + */ + switch (which) { + + case LEAF_begemotNgControlNodeName: + return (string_get(value, snmp_nodename, -1)); + + case LEAF_begemotNgResBufSiz: + value->v.integer = resbufsiz; + break; + + case LEAF_begemotNgTimeout: + value->v.integer = timeout; + break; + + case LEAF_begemotNgDebugLevel: + value->v.uint32 = debug_level; + break; + + default: + abort(); + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_SET: + switch (which) { + + case LEAF_begemotNgControlNodeName: + /* only at initialisation */ + if (community != COMM_INITIALIZE) + return (SNMP_ERR_NOT_WRITEABLE); + + if (snmp_node != 0) + return (SNMP_ERR_NOT_WRITEABLE); + + if ((ret = string_save(value, ctx, -1, &snmp_nodename)) + != SNMP_ERR_NOERROR) + return (ret); + + if (NgMkSockNode(snmp_nodename, &csock, &dsock) < 0) { + syslog(LOG_ERR, "NgMkSockNode: %m"); + string_rollback(ctx, &snmp_nodename); + return (SNMP_ERR_GENERR); + } + snmp_node = ng_node_id(".:"); + + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNgResBufSiz: + ctx->scratch->int1 = resbufsiz; + if (value->v.integer < 1024 || + value->v.integer > 0x10000) + return (SNMP_ERR_WRONG_VALUE); + resbufsiz = value->v.integer; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNgTimeout: + ctx->scratch->int1 = timeout; + if (value->v.integer < 10 || + value->v.integer > 10000) + return (SNMP_ERR_WRONG_VALUE); + timeout = value->v.integer; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNgDebugLevel: + ctx->scratch->int1 = debug_level; + debug_level = value->v.uint32; + NgSetDebug(debug_level); + return (SNMP_ERR_NOERROR); + } + abort(); + + case SNMP_OP_ROLLBACK: + switch (which) { + + case LEAF_begemotNgControlNodeName: + string_rollback(ctx, &snmp_nodename); + close(csock); + close(dsock); + snmp_node = 0; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNgResBufSiz: + resbufsiz = ctx->scratch->int1; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNgTimeout: + timeout = ctx->scratch->int1; + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNgDebugLevel: + debug_level = ctx->scratch->int1; + NgSetDebug(debug_level); + return (SNMP_ERR_NOERROR); + } + abort(); + + case SNMP_OP_COMMIT: + switch (which) { + + case LEAF_begemotNgControlNodeName: + string_commit(ctx); + return (SNMP_ERR_NOERROR); + + case LEAF_begemotNgResBufSiz: + case LEAF_begemotNgTimeout: + case LEAF_begemotNgDebugLevel: + return (SNMP_ERR_NOERROR); + } + abort(); + } + abort(); +} + +int +op_ng_stats(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: + value->v.uint32 = stats[value->var.subs[sub - 1] - 1]; + return (SNMP_ERR_NOERROR); + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + abort(); + } + abort(); +} + +/* + * Netgraph type table + */ +static int +fetch_types(void) +{ + struct ngtype *t; + struct typelist *typelist; + struct ng_mesg *resp; + u_int u, i; + + if (this_tick <= ngtype_tick) + return (0); + + while ((t = TAILQ_FIRST(&ngtype_list)) != NULL) { + TAILQ_REMOVE(&ngtype_list, t, link); + free(t); + } + + if ((resp = ng_dialog_id(snmp_node, NGM_GENERIC_COOKIE, + NGM_LISTTYPES, NULL, 0)) == NULL) + return (SNMP_ERR_GENERR); + typelist = (struct typelist *)(void *)resp->data; + + for (u = 0; u < typelist->numtypes; u++) { + if ((t = malloc(sizeof(*t))) == NULL) { + free(resp); + return (SNMP_ERR_GENERR); + } + strcpy(t->name, typelist->typeinfo[u].type_name); + t->index.subs[0] = strlen(t->name); + t->index.len = t->index.subs[0] + 1; + for (i = 0; i < t->index.subs[0]; i++) + t->index.subs[i + 1] = t->name[i]; + + INSERT_OBJECT_OID(t, &ngtype_list); + } + + ngtype_tick = this_tick; + + free(resp); + return (0); +} + +/* + * Try to load the netgraph type with the given name. We assume, that + * type 'type' is implemented in the kernel module 'ng_type'. + */ +static int +ngtype_load(const u_char *name, size_t namelen) +{ + char *mod; + int ret; + + if ((mod = malloc(namelen + 4)) == NULL) + return (-1); + strcpy(mod, "ng_"); + strncpy(mod + 3, name, namelen); + mod[namelen + 3] = '\0'; + + ret = kldload(mod); + free(mod); + return (ret); +} + +/* + * Unload a netgraph type. + */ +static int +ngtype_unload(const u_char *name, size_t namelen) +{ + char *mod; + int id; + + if ((mod = malloc(namelen + 4)) == NULL) + return (-1); + strcpy(mod, "ng_"); + strncpy(mod + 3, name, namelen); + mod[namelen + 3] = '\0'; + + if ((id = kldfind(mod)) == -1) { + free(mod); + return (-1); + } + free(mod); + return (kldunload(id)); +} + +int +op_ng_type(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + struct ngtype *t; + u_char *name; + size_t namelen; + int status = 1; + int ret; + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((ret = fetch_types()) != 0) + return (ret); + if ((t = NEXT_OBJECT_OID(&ngtype_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &t->index); + break; + + case SNMP_OP_GET: + if ((ret = fetch_types()) != 0) + return (ret); + if ((t = FIND_OBJECT_OID(&ngtype_list, &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if (index_decode(&value->var, sub, iidx, &name, &namelen)) + return (SNMP_ERR_NO_CREATION); + if (namelen == 0 || namelen > NG_TYPELEN) { + free(name); + return (SNMP_ERR_NO_CREATION); + } + if ((ret = fetch_types()) != 0) { + free(name); + return (ret); + } + t = FIND_OBJECT_OID(&ngtype_list, &value->var, sub); + + if (which != LEAF_begemotNgTypeStatus) { + free(name); + if (t != NULL) + return (SNMP_ERR_NOT_WRITEABLE); + return (SNMP_ERR_NO_CREATION); + } + if (!TRUTH_OK(value->v.integer)) { + free(name); + return (SNMP_ERR_WRONG_VALUE); + } + ctx->scratch->int1 = TRUTH_GET(value->v.integer); + ctx->scratch->int1 |= (t != NULL) << 1; + ctx->scratch->ptr2 = name; + ctx->scratch->int2 = namelen; + + if (t == NULL) { + /* type not loaded */ + if (ctx->scratch->int1 & 1) { + /* request to load */ + if (ngtype_load(name, namelen) == -1) { + free(name); + if (errno == ENOENT) + return (SNMP_ERR_INCONS_NAME); + else + return (SNMP_ERR_GENERR); + } + } + } else { + /* is type loaded */ + if (!(ctx->scratch->int1 & 1)) { + /* request to unload */ + if (ngtype_unload(name, namelen) == -1) { + free(name); + return (SNMP_ERR_GENERR); + } + } + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + ret = SNMP_ERR_NOERROR; + if (!(ctx->scratch->int1 & 2)) { + /* did not exist */ + if (ctx->scratch->int1 & 1) { + /* request to load - unload */ + if (ngtype_unload(ctx->scratch->ptr2, + ctx->scratch->int2) == -1) + ret = SNMP_ERR_UNDO_FAILED; + } + } else { + /* did exist */ + if (!(ctx->scratch->int1 & 1)) { + /* request to unload - reload */ + if (ngtype_load(ctx->scratch->ptr2, + ctx->scratch->int2) == -1) + ret = SNMP_ERR_UNDO_FAILED; + } + } + free(ctx->scratch->ptr2); + return (ret); + + case SNMP_OP_COMMIT: + free(ctx->scratch->ptr2); + return (SNMP_ERR_NOERROR); + + default: + abort(); + } + + /* + * Come here for GET and COMMIT + */ + switch (which) { + + case LEAF_begemotNgTypeStatus: + value->v.integer = status; + break; + + default: + abort(); + } + return (SNMP_ERR_NOERROR); +} + +/* + * Implement the node table + */ +static int +find_node(const struct asn_oid *oid, u_int sub, struct nodeinfo *info) +{ + ng_ID_t id = oid->subs[sub]; + struct ng_mesg *resp; + + if ((resp = ng_dialog_id(id, NGM_GENERIC_COOKIE, NGM_NODEINFO, + NULL, 0)) == NULL) + return (-1); + + *info = *(struct nodeinfo *)(void *)resp->data; + free(resp); + return (0); +} + +static int +ncmp(const void *p1, const void *p2) +{ + const struct nodeinfo *i1 = p1; + const struct nodeinfo *i2 = p2; + + if (i1->id < i2->id) + return (-1); + if (i1->id > i2->id) + return (+1); + return (0); +} + +static int +find_node_next(const struct asn_oid *oid, u_int sub, struct nodeinfo *info) +{ + u_int idxlen = oid->len - sub; + struct ng_mesg *resp; + struct namelist *list; + ng_ID_t id; + u_int i; + + if ((resp = ng_dialog_id(snmp_node, NGM_GENERIC_COOKIE, NGM_LISTNODES, + NULL, 0)) == NULL) + return (-1); + list = (struct namelist *)(void *)resp->data; + + qsort(list->nodeinfo, list->numnames, sizeof(list->nodeinfo[0]), ncmp); + + if (idxlen == 0) { + if (list->numnames == 0) { + free(resp); + return (-1); + } + *info = list->nodeinfo[0]; + free(resp); + return (0); + } + id = oid->subs[sub]; + + for (i = 0; i < list->numnames; i++) + if (list->nodeinfo[i].id > id) { + *info = list->nodeinfo[i]; + free(resp); + return (0); + } + + free(resp); + return (-1); +} + +int +op_ng_node(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + u_int idxlen = value->var.len - sub; + struct nodeinfo nodeinfo; + + switch (op) { + + case SNMP_OP_GETNEXT: + if (find_node_next(&value->var, sub, &nodeinfo) == -1) + return (SNMP_ERR_NOSUCHNAME); + value->var.len = sub + 1; + value->var.subs[sub] = nodeinfo.id; + break; + + case SNMP_OP_GET: + if (idxlen != 1) + return (SNMP_ERR_NOSUCHNAME); + if (find_node(&value->var, sub, &nodeinfo) == -1) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if (idxlen != 1) + return (SNMP_ERR_NO_CREATION); + if (find_node(&value->var, sub, &nodeinfo) == -1) + return (SNMP_ERR_NO_CREATION); + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + default: + abort(); + } + + /* + * Come here for GET and COMMIT + */ + switch (which) { + + case LEAF_begemotNgNodeStatus: + value->v.integer = 1; + break; + case LEAF_begemotNgNodeName: + return (string_get(value, nodeinfo.name, -1)); + case LEAF_begemotNgNodeType: + return (string_get(value, nodeinfo.type, -1)); + case LEAF_begemotNgNodeHooks: + value->v.uint32 = nodeinfo.hooks; + break; + + default: + abort(); + } + return (SNMP_ERR_NOERROR); +} + +/* + * Implement the hook table + */ +static int +find_hook(int32_t id, const u_char *hook, size_t hooklen, struct linkinfo *info) +{ + struct ng_mesg *resp; + struct hooklist *list; + u_int i; + + if ((resp = ng_dialog_id(id, NGM_GENERIC_COOKIE, + NGM_LISTHOOKS, NULL, 0)) == NULL) + return (-1); + + list = (struct hooklist *)(void *)resp->data; + + for (i = 0; i < list->nodeinfo.hooks; i++) { + if (strlen(list->link[i].ourhook) == hooklen && + strncmp(list->link[i].ourhook, hook, hooklen) == 0) { + *info = list->link[i]; + free(resp); + return (0); + } + } + free(resp); + return (-1); +} + +static int +hook_cmp(const void *p1, const void *p2) +{ + const struct linkinfo *i1 = p1; + const struct linkinfo *i2 = p2; + + if (strlen(i1->ourhook) < strlen(i2->ourhook)) + return (-1); + if (strlen(i1->ourhook) > strlen(i2->ourhook)) + return (+1); + return (strcmp(i1->ourhook, i2->ourhook)); +} + +static int +find_hook_next(const struct asn_oid *oid, u_int sub, struct nodeinfo *nodeinfo, + struct linkinfo *linkinfo) +{ + u_int idxlen = oid->len - sub; + struct namelist *list; + struct ng_mesg *resp; + struct hooklist *hooks; + struct ng_mesg *resp1; + u_int node_index; + struct asn_oid idx; + u_int i, j; + + /* + * Get and sort Node list + */ + if ((resp = ng_dialog_id(snmp_node, NGM_GENERIC_COOKIE, NGM_LISTNODES, + NULL, 0)) == NULL) + return (-1); + list = (struct namelist *)(void *)resp->data; + + qsort(list->nodeinfo, list->numnames, sizeof(list->nodeinfo[0]), ncmp); + + /* + * If we have no index, take the first node and return the + * first hook. + */ + if (idxlen == 0) { + node_index = 0; + goto return_first_hook; + } + + /* + * Locate node + */ + for (node_index = 0; node_index < list->numnames; node_index++) + if (list->nodeinfo[node_index].id >= oid->subs[sub]) + break; + + /* + * If we have only the node part of the index take, or + * there is no node with that Id, take the first hook of that node. + */ + if (idxlen == 1 || node_index >= list->numnames || + list->nodeinfo[node_index].id > oid->subs[sub]) + goto return_first_hook; + + /* + * We had an exact match on the node id and have (at last part) + * of the hook name index. Loop through the hooks of the node + * and find the next one. + */ + if ((resp1 = ng_dialog_id(list->nodeinfo[node_index].id, + NGM_GENERIC_COOKIE, NGM_LISTHOOKS, NULL, 0)) == NULL) { + free(resp); + return (-1); + } + hooks = (struct hooklist *)(void *)resp1->data; + if (hooks->nodeinfo.hooks > 0) { + qsort(hooks->link, hooks->nodeinfo.hooks, + sizeof(hooks->link[0]), hook_cmp); + for (i = 0; i < hooks->nodeinfo.hooks; i++) { + idx.len = strlen(hooks->link[i].ourhook) + 1; + idx.subs[0] = idx.len - 1; + for (j = 0; j < idx.len; j++) + idx.subs[j + 1] = hooks->link[i].ourhook[j]; + if (index_compare(oid, sub + 1, &idx) < 0) + break; + } + if (i < hooks->nodeinfo.hooks) { + *nodeinfo = hooks->nodeinfo; + *linkinfo = hooks->link[i]; + + free(resp); + free(resp1); + return (0); + } + } + + /* no hook found larger than the index on the index node - take + * first hook of next node */ + free(resp1); + node_index++; + + return_first_hook: + while (node_index < list->numnames) { + if ((resp1 = ng_dialog_id(list->nodeinfo[node_index].id, + NGM_GENERIC_COOKIE, NGM_LISTHOOKS, NULL, 0)) == NULL) + break; + hooks = (struct hooklist *)(void *)resp1->data; + if (hooks->nodeinfo.hooks > 0) { + qsort(hooks->link, hooks->nodeinfo.hooks, + sizeof(hooks->link[0]), hook_cmp); + + *nodeinfo = hooks->nodeinfo; + *linkinfo = hooks->link[0]; + + free(resp); + free(resp1); + return (0); + } + + /* if we don't have hooks, try next node */ + free(resp1); + node_index++; + } + + free(resp); + return (-1); +} + +int +op_ng_hook(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + struct linkinfo linkinfo; + struct nodeinfo nodeinfo; + u_int32_t lid; + u_char *hook; + size_t hooklen; + u_int i; + + switch (op) { + + case SNMP_OP_GETNEXT: + if (find_hook_next(&value->var, sub, &nodeinfo, &linkinfo) == -1) + return (SNMP_ERR_NOSUCHNAME); + + value->var.len = sub + 1 + 1 + strlen(linkinfo.ourhook); + value->var.subs[sub] = nodeinfo.id; + value->var.subs[sub + 1] = strlen(linkinfo.ourhook); + for (i = 0; i < strlen(linkinfo.ourhook); i++) + value->var.subs[sub + i + 2] = + linkinfo.ourhook[i]; + break; + + case SNMP_OP_GET: + if (index_decode(&value->var, sub, iidx, &lid, + &hook, &hooklen)) + return (SNMP_ERR_NOSUCHNAME); + if (find_hook(lid, hook, hooklen, &linkinfo) == -1) { + free(hook); + return (SNMP_ERR_NOSUCHNAME); + } + free(hook); + break; + + case SNMP_OP_SET: + if (index_decode(&value->var, sub, iidx, &lid, + &hook, &hooklen)) + return (SNMP_ERR_NO_CREATION); + if (find_hook(lid, hook, hooklen, &linkinfo) == -1) { + free(hook); + return (SNMP_ERR_NO_CREATION); + } + free(hook); + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + default: + abort(); + + } + + switch (which) { + + case LEAF_begemotNgHookStatus: + value->v.integer = 1; + break; + case LEAF_begemotNgHookPeerNodeId: + value->v.uint32 = linkinfo.nodeinfo.id; + break; + case LEAF_begemotNgHookPeerHook: + return (string_get(value, linkinfo.peerhook, -1)); + case LEAF_begemotNgHookPeerType: + return (string_get(value, linkinfo.nodeinfo.type, -1)); + default: + abort(); + } + return (SNMP_ERR_NOERROR); +} diff --git a/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.h b/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.h new file mode 100644 index 00000000000..21e553c3091 --- /dev/null +++ b/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * 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. + * + * 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. + * + * $FreeBSD$ + * + * Netgraph interface for SNMPd. Exported stuff. + */ +#ifndef SNMP_NETGRAPH_H_ +#define SNMP_NETGRAPH_H_ + +#include + +extern ng_ID_t snmp_node; +extern u_char *snmp_nodename; + +typedef void ng_cookie_f(const struct ng_mesg *, const char *, ng_ID_t, void *); +typedef void ng_hook_f(const char *, const u_char *, size_t, void *); + +void *ng_register_cookie(const struct lmodule *, u_int32_t cookie, + ng_ID_t, ng_cookie_f *, void *); +void ng_unregister_cookie(void *reg); + +void *ng_register_hook(const struct lmodule *, const char *, + ng_hook_f *, void *); +void ng_unregister_hook(void *reg); + +void ng_unregister_module(const struct lmodule *); + +int ng_output(const char *path, u_int cookie, u_int opcode, + const void *arg, size_t arglen); +int ng_output_node(const char *node, u_int cookie, u_int opcode, + const void *arg, size_t arglen); +int ng_output_id(ng_ID_t node, u_int cookie, u_int opcode, + const void *arg, size_t arglen); + +struct ng_mesg *ng_dialog(const char *path, u_int cookie, u_int opcode, + const void *arg, size_t arglen); +struct ng_mesg *ng_dialog_node(const char *node, u_int cookie, u_int opcode, + const void *arg, size_t arglen); +struct ng_mesg *ng_dialog_id(ng_ID_t id, u_int cookie, u_int opcode, + const void *arg, size_t arglen); + +int ng_send_data(const char *hook, const void *sndbuf, size_t sndlen); + +ng_ID_t ng_mkpeer_id(ng_ID_t, const char *name, const char *type, + const char *hook, const char *peerhook); +int ng_connect_node(const char *node, const char *ourhook, const char *peerhook); +int ng_connect_id(ng_ID_t id, const char *ourhook, const char *peerhook); +int ng_connect2_id(ng_ID_t id, ng_ID_t peer, const char *ourhook, + const char *peerhook); +int ng_connect2_tee_id(ng_ID_t id, ng_ID_t peer, const char *ourhook, + const char *peerhook); +int ng_rmhook(const char *ourhook); +int ng_rmhook_id(ng_ID_t, const char *); +int ng_rmhook_tee_id(ng_ID_t, const char *); +int ng_shutdown_id(ng_ID_t); + +ng_ID_t ng_next_node_id(ng_ID_t node, const char *type, const char *hook); +ng_ID_t ng_node_id(const char *path); +ng_ID_t ng_node_id_node(const char *node); +ng_ID_t ng_node_name(ng_ID_t, char *); +ng_ID_t ng_node_type(ng_ID_t, char *); +int ng_peer_hook_id(ng_ID_t, const char *, char *); + +#endif -- 2.45.2