Add SNMP support (bug #6439)
authorMark Spencer <markster@digium.com>
Sun, 26 Feb 2006 20:46:11 +0000 (20:46 +0000)
committerMark Spencer <markster@digium.com>
Sun, 26 Feb 2006 20:46:11 +0000 (20:46 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@11193 65c4cc65-6c06-0410-ace0-fbb531ad65f3

configs/res_snmp.conf.sample [new file with mode: 0644]
doc/asterisk-mib.txt [new file with mode: 0644]
doc/digium-mib.txt [new file with mode: 0644]
doc/snmp.txt [new file with mode: 0644]
res/Makefile
res/res_snmp.c [new file with mode: 0644]
res/snmp/agent.c [new file with mode: 0644]
res/snmp/agent.h [new file with mode: 0644]

diff --git a/configs/res_snmp.conf.sample b/configs/res_snmp.conf.sample
new file mode 100644 (file)
index 0000000..5ca09d5
--- /dev/null
@@ -0,0 +1,10 @@
+;
+; Configuration file for res_snmp
+;
+
+[general]
+; We run as a subagent per default -- to run as a full agent
+; we must run as root (to be able to bind to port 161) 
+;subagent = yes
+; SNMP must be explicitly enabled to be active
+;enabled = yes
diff --git a/doc/asterisk-mib.txt b/doc/asterisk-mib.txt
new file mode 100644 (file)
index 0000000..f4d6656
--- /dev/null
@@ -0,0 +1,717 @@
+ASTERISK-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+       OBJECT-TYPE, MODULE-IDENTITY, Integer32, Counter32, TimeTicks
+               FROM SNMPv2-SMI
+
+       TEXTUAL-CONVENTION, DisplayString, TruthValue
+               FROM SNMPv2-TC
+
+       digium
+               FROM DIGIUM-MIB;
+
+asterisk MODULE-IDENTITY
+       LAST-UPDATED    "200602041900Z"
+       ORGANIZATION    "Digium, Inc."
+       CONTACT-INFO
+               "Mark Spencer
+               Email: markster@digium.com"
+       DESCRIPTION
+               "Asterisk is an Open Source PBX.  This MIB defined
+               objects for managing Asterisk instances."
+       ::= { digium 1 }
+
+asteriskVersion                OBJECT IDENTIFIER ::= { asterisk 1 }
+asteriskConfiguration  OBJECT IDENTIFIER ::= { asterisk 2 }
+asteriskModules                OBJECT IDENTIFIER ::= { asterisk 3 }
+asteriskIndications    OBJECT IDENTIFIER ::= { asterisk 4 }
+asteriskChannels       OBJECT IDENTIFIER ::= { asterisk 5 }
+
+-- asteriskVersion
+
+astVersionString OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Text version string of the version of Asterisk that
+               the SNMP Agent was compiled to run against."
+       ::= { asteriskVersion 1 }
+
+astVersionTag OBJECT-TYPE
+       SYNTAX          Unsigned32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "SubVersion revision of the version of Asterisk that
+               the SNMP Agent was compiled to run against -- this is
+               typically 0 for release-versions of Asterisk."
+       ::= { asteriskVersion 2 }
+
+-- asteriskConfiguration
+
+astConfigUpTime OBJECT-TYPE
+       SYNTAX          TimeTicks
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Time ticks since Asterisk was started."
+       ::= { asteriskConfiguration 1 }
+
+astConfigReloadTime OBJECT-TYPE
+       SYNTAX          TimeTicks
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Time ticks since Asterisk was last reloaded."
+       ::= { asteriskConfiguration 2 }
+
+astConfigPid OBJECT-TYPE
+       SYNTAX          Integer32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "The process id of the running Asterisk process."
+       ::= { asteriskConfiguration 3 }
+
+astConfigSocket OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "The control socket for giving Asterisk commands."
+       ::= { asteriskConfiguration 4 }
+
+-- asteriskModules
+
+astNumModules OBJECT-TYPE
+       SYNTAX          Integer32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Number of modules currently loaded into Asterisk."
+       ::= { asteriskModules 1 }
+
+-- asteriskIndications
+
+astNumIndications OBJECT-TYPE
+       SYNTAX          Integer32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Number of indications currently defined in Asterisk."
+       ::= { asteriskIndications 1 }
+
+astCurrentIndication OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Default indication zone to use."
+       ::= { asteriskIndications 2 }
+
+astIndicationsTable OBJECT-TYPE
+       SYNTAX          SEQUENCE OF AstIndicationsEntry
+       MAX-ACCESS      not-accessible
+       STATUS          current
+       DESCRIPTION
+               "Table with all the indication zones currently know to
+               the running Asterisk instance."
+       ::= { asteriskIndications 3 }
+
+astIndicationsEntry OBJECT-TYPE
+       SYNTAX          AstIndicationsEntry
+       MAX-ACCESS      not-accessible
+       STATUS          current
+       DESCRIPTION
+               "Information about a single indication zone."
+       INDEX           { astIndIndex }
+       ::= { astIndicationsTable 1 }
+
+AstIndicationsEntry ::= SEQUENCE {
+       astIndIndex             Integer32,
+       astIndCountry           DisplayString,
+       astIndAlias             DisplayString,
+       astIndDescription       DisplayString
+}
+
+astIndIndex OBJECT-TYPE
+       SYNTAX          Integer32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Numerical index into the table of indication zones."
+       ::= { astIndicationsEntry 1 }
+
+astIndCountry OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Country for which the indication zone is valid,
+               typically this is the ISO 2-letter code of the country."
+       ::= { astIndicationsEntry 2 }
+
+astIndAlias OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               ""
+       ::= { astIndicationsEntry 3 }
+
+astIndDescription OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Description of the indication zone, usually the full
+               name of the country it is valid for."
+       ::= { astIndicationsEntry 4 }
+
+-- asteriskChannels
+
+astNumChannels OBJECT-TYPE
+       SYNTAX          Integer32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Current number of active channels."
+       ::= { asteriskChannels 1 }
+
+astChanTable OBJECT-TYPE
+       SYNTAX          SEQUENCE OF AstChanEntry
+       MAX-ACCESS      not-accessible
+       STATUS          current
+       DESCRIPTION
+               "Table with details of the currently active channels
+               in the Asterisk instance."
+       ::= { asteriskChannels 2 }
+
+astChanEntry OBJECT-TYPE
+       SYNTAX          AstChanEntry
+       MAX-ACCESS      not-accessible
+       STATUS          current
+       DESCRIPTION
+               "Details of a single channel."
+       INDEX           { astChanIndex }
+       ::= { astChanTable 1 }
+
+AstChanEntry ::= SEQUENCE {
+       astChanIndex            Integer32,
+       astChanName             DisplayString,
+       astChanLanguage         DisplayString,
+       astChanType             DisplayString,
+       astChanMusicClass       DisplayString,
+       astChanBridge           DisplayString,
+       astChanMasq             DisplayString,
+       astChanMasqr            DisplayString,
+       astChanWhenHangup       TimeTicks,
+       astChanApp              DisplayString,
+       astChanData             DisplayString,
+       astChanContext          DisplayString,
+       astChanMacroContext     DisplayString,
+       astChanMacroExten       DisplayString,
+       astChanMacroPri         Integer32,
+       astChanExten            DisplayString,
+       astChanPri              Integer32,
+       astChanAccountCode      DisplayString,
+       astChanForwardTo        DisplayString,
+       astChanUniqueId         DisplayString,
+       astChanCallGroup        Unsigned32,
+       astChanPickupGroup      Unsigned32,
+       astChanState            INTEGER,
+       astChanMuted            TruthValue,
+       astChanRings            Integer32,
+       astChanCidDNID          DisplayString,
+       astChanCidNum           DisplayString,
+       astChanCidName          DisplayString,
+       astChanCidANI           DisplayString,
+       astChanCidRDNIS         DisplayString,
+       astChanCidPresentation  DisplayString,
+       astChanCidANI2          Integer32,
+       astChanCidTON           Integer32,
+       astChanCidTNS           Integer32,
+       astChanAMAFlags         INTEGER,
+       astChanADSI             INTEGER,
+       astChanToneZone         DisplayString,
+       astChanHangupCause      INTEGER,
+       astChanVariables        DisplayString,
+       astChanFlags            BITS,
+       astChanTransferCap      INTEGER
+}
+
+astChanIndex OBJECT-TYPE
+       SYNTAX          Integer32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Index into the channel table."
+       ::= { astChanEntry 1 }
+
+astChanName OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Name of the currentl channel."
+       ::= { astChanEntry 2 }
+
+astChanLanguage OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Which language the current channel is configured to
+               use -- used mainly for prompts."
+       ::= { astChanEntry 3 }
+
+astChanType OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Underlying technology for the current channel."
+       ::= { astChanEntry 4 }
+
+astChanMusicClass OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Music class to be used for Music on Hold for this
+               channel."
+       ::= { astChanEntry 5 }
+
+astChanBridge OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Which channel this channel is currently bridged (in a
+               conversation) with."
+       ::= { astChanEntry 6 }
+
+astChanMasq OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Channel masquerading for us."
+       ::= { astChanEntry 7 }
+
+astChanMasqr OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Channel we are masquerading for."
+       ::= { astChanEntry 8 }
+
+astChanWhenHangup OBJECT-TYPE
+       SYNTAX          TimeTicks
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "How long until this channel will be hung up."
+       ::= { astChanEntry 9 }
+
+astChanApp OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Current application for the channel."
+       ::= { astChanEntry 10 }
+
+astChanData OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Arguments passed to the current application."
+       ::= { astChanEntry 11 }
+
+astChanContext OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Current extension context."
+       ::= { astChanEntry 12 }
+
+astChanMacroContext OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Current macro context."
+       ::= { astChanEntry 13 }
+
+astChanMacroExten OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Current macro extension."
+       ::= { astChanEntry 14 }
+
+astChanMacroPri OBJECT-TYPE
+       SYNTAX          Integer32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Current macro priority."
+       ::= { astChanEntry 15 }
+
+astChanExten OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Current extension."
+       ::= { astChanEntry 16 }
+
+astChanPri OBJECT-TYPE
+       SYNTAX          Integer32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Current priority."
+       ::= { astChanEntry 17 }
+
+astChanAccountCode OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Account Code for billing."
+       ::= { astChanEntry 18 }
+
+astChanForwardTo OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Where to forward to if asked to dial on this
+               interface."
+       ::= { astChanEntry 19 }
+
+astChanUniqueId OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Unique Channel Identifier."
+       ::= { astChanEntry 20 }
+
+astChanCallGroup OBJECT-TYPE
+       SYNTAX          Unsigned32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Call Group."
+       ::= { astChanEntry 21 }
+
+astChanPickupGroup OBJECT-TYPE
+       SYNTAX          Unsigned32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Pickup Group."
+       ::= { astChanEntry 22 }
+
+astChanState OBJECT-TYPE
+       SYNTAX          INTEGER {
+               stateDown(0),
+               stateReserved(1),
+               stateOffHook(2),
+               stateDialing(3),
+               stateRing(4),
+               stateRinging(5),
+               stateUp(6),
+               stateBusy(7),
+               stateDialingOffHook(8),
+               statePreRing(9)
+       }
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Channel state."
+       ::= { astChanEntry 23 }
+
+astChanMuted OBJECT-TYPE
+       SYNTAX          TruthValue
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Transmission of voice data has been muted."
+       ::= { astChanEntry 24 }
+
+astChanRings OBJECT-TYPE
+       SYNTAX          Integer32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Number of rings so far."
+       ::= { astChanEntry 25 }
+
+astChanCidDNID OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Dialled Number ID."
+       ::= { astChanEntry 26 }
+
+astChanCidNum OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Caller Number."
+       ::= { astChanEntry 27 }
+
+astChanCidName OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Caller Name."
+       ::= { astChanEntry 28 }
+
+astCanCidANI OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "ANI"
+       ::= { astChanEntry 29 }
+
+astChanCidRDNIS OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Redirected Dialled Number Service."
+       ::= { astChanEntry 30 }
+
+astChanCidPresentation OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Number Presentation/Screening."
+       ::= { astChanEntry 31 }
+
+astChanCidANI2 OBJECT-TYPE
+       SYNTAX          Integer32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "ANI 2 (info digit)."
+       ::= { astChanEntry 32 }
+
+astChanCidTON OBJECT-TYPE
+       SYNTAX          Integer32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Type of Number."
+       ::= { astChanEntry 33 }
+
+astChanCidTNS OBJECT-TYPE
+       SYNTAX          Integer32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Transit Network Select."
+       ::= { astChanEntry 34 }
+
+astChanAMAFlags OBJECT-TYPE
+       SYNTAX          INTEGER {
+               Default(0),
+               Omit(1),
+               Billing(2),
+               Documentation(3)
+       }
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "AMA Flags."
+       ::= { astChanEntry 35 }
+
+astChanADSI OBJECT-TYPE
+       SYNTAX          INTEGER {
+               Unknown(0),
+               Available(1),
+               Unavailable(2),
+               OffHookOnly(3)
+       }
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Whether or not ADSI is detected on CPE."
+       ::= { astChanEntry 36 }
+
+astChanToneZone OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Indication zone to use for channel."
+       ::= { astChanEntry 37 }
+
+astChanHangupCause OBJECT-TYPE
+       SYNTAX          INTEGER {
+               NotDefined(0),
+               Unregistered(3),
+               Normal(16),
+               Busy(17),
+               NoAnswer(19),
+               Congestion(34),
+               Failure(38),
+               NoSuchDriver(66)
+       }
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Why is the channel hung up."
+       ::= { astChanEntry 38 }
+
+astChanVariables OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Channel Variables defined for this channel."
+       ::= { astChanEntry 39 }
+
+astChanFlags OBJECT-TYPE
+       SYNTAX          BITS {
+               WantsJitter(0),
+               DeferDTMF(1),
+               WriteInterrupt(2),
+               Blocking(3),
+               Zombie(4),
+               Exception(5),
+               MusicOnHold(6),
+               Spying(7),
+               NativeBridge(8),
+               AutoIncrementingLoop(9)
+       }
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Flags set on this channel."
+       ::= { astChanEntry 40 }
+
+astChanTransferCap OBJECT-TYPE
+       SYNTAX          INTEGER {
+               Speech(0),
+               Digital(8),
+               RestrictedDigital(9),
+               3kAudio(16),
+               DigitalWithTones(17),
+               Video(24)
+       }
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Transfer Capabilities for this channel."
+       ::= { astChanEntry 41 }
+
+astNumChanTypes OBJECT-TYPE
+       SYNTAX          Integer32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Number of channel types (technologies) supported."
+       ::= { asteriskChannels 3 }
+
+astChanTypeTable OBJECT-TYPE
+       SYNTAX          SEQUENCE OF AstChanTypeEntry
+       MAX-ACCESS      not-accessible
+       STATUS          current
+       DESCRIPTION
+               "Table with details of the supported channel types."
+       ::= { asteriskChannels 4 }
+
+astChanTypeEntry OBJECT-TYPE
+       SYNTAX          AstChanTypeEntry
+       MAX-ACCESS      not-accessible
+       STATUS          current
+       DESCRIPTION
+               "Information about a technology we support, including
+               how many channels are currently using this technology."
+       INDEX           { astChanTypeIndex }
+       ::= { astChanTypeTable 1 }
+
+AstChanTypeEntry ::= SEQUENCE {
+       astChanTypeIndex        Integer32,
+       astChanTypeName         DisplayString,
+       astChanTypeDesc         DisplayString,
+       astChanTypeDeviceState  Integer32,
+       astChanTypeIndications  Integer32,
+       astChanTypeTransfer     Integer32,
+       astChanTypeChannels     Gauge32
+}
+
+astChanTypeIndex OBJECT-TYPE
+       SYNTAX          Integer32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Index into the table of channel types."
+       ::= { astChanTypeEntry 1 }
+
+astChanTypeName OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Unique name of the technology we are describing."
+       ::= { astChanTypeEntry 2 }
+
+astChanTypeDesc OBJECT-TYPE
+       SYNTAX          DisplayString
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Description of the channel type (technology)."
+       ::= { astChanTypeEntry 3 }
+
+astChanTypeDeviceState OBJECT-TYPE
+       SYNTAX          TruthValue
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Whether the current technology can hold device states."
+       ::= { astChanTypeEntry 4 }
+
+astChanTypeIndications OBJECT-TYPE
+       SYNTAX          TruthValue
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Whether the current technology supports progress indication."
+       ::= { astChanTypeEntry 5 }
+
+astChanTypeTransfer OBJECT-TYPE
+       SYNTAX          TruthValue
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Whether the current technology supports transfers, where
+               Asterisk can get out from inbetween two bridged channels."
+       ::= { astChanTypeEntry 6 }
+
+astChanTypeChannels OBJECT-TYPE
+       SYNTAX          Gauge32
+       MAX-ACCESS      read-only
+       STATUS          current
+       DESCRIPTION
+               "Number of active channels using the current technology."
+       ::= { astChanTypeEntry 7 }
+
+END
diff --git a/doc/digium-mib.txt b/doc/digium-mib.txt
new file mode 100644 (file)
index 0000000..018a080
--- /dev/null
@@ -0,0 +1,17 @@
+DIGIUM-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+       enterprises
+               FROM SNMPv2-SMI;
+
+digium MODULE-IDENTITY
+       LAST-UPDATED    "200602041900Z"
+       ORGANIZATION    "Digium, Inc."
+       CONTACT-INFO
+               "Mark Spencer
+               Email: markster@digium.com"
+       DESCRIPTION
+               ""
+       ::= { enterprises 22736 }
+
+END
diff --git a/doc/snmp.txt b/doc/snmp.txt
new file mode 100644 (file)
index 0000000..afab91c
--- /dev/null
@@ -0,0 +1,36 @@
+Asterisk SNMP Support
+---------------------
+
+Rudimentary support for SNMP access to Asterisk is available.  To build
+this, one needs to have Net-SNMP development headers and libraries on
+the build system, including any libraries Net-SNMP depends on.
+
+Note that on some (many?) Linux-distributions the dependency list in
+the net-snmp-devel list is not complete, and additional RPMs will need
+to be installed.  This is typically seen as attempts to build res_snmp
+as net-snmp-devel is available, but then failures to find certain
+libraries.
+
+SNMP support comes in two varieties -- as a sub-agent to a running SNMP
+daemon using the AgentX protocol, or as a full standalone agent.  If
+you wish to run a full standalone agent, Asterisk must run as root in
+order to find to port 161.
+
+Configuring access when running as a full agent is something that is
+left as an exercise to the reader.
+
+To enable access to the Asterisk SNMP subagent from a master SNMP
+daemon, one will need to enable AgentX support, and also make sure that
+Asterisk will be able to access the Unix domain socket.  One way of
+doing this is to add the following to /etc/snmp/snmpd.conf:
+
+       # Enable AgentX support
+       master agentx
+
+       # Set permissions on AgentX socket and containing
+       # directory such that process in group 'asterisk'
+       # will be able to connect
+       agentXPerms  0660 0550 nobody asterisk
+
+This assumes that you run Asterisk under group 'asterisk' (and does
+not care what user you run as).
index 2759f4e..08ee8e1 100644 (file)
@@ -32,6 +32,11 @@ ifeq (${OSPLIB},)
   MODS:=$(filter-out res_osp.so,$(MODS))
 endif
 
+ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/net-snmp/net-snmp-config.h),)
+       SNMP_LDLIBS+=$(shell net-snmp-config --agent-libs)
+       MODS+=res_snmp.so
+endif
+
 ifeq (${WITH_SMDI},)
   MODS:=$(filter-out res_smdi.so,$(MODS))
 endif
@@ -108,6 +113,9 @@ res_features.so: res_features.o
 res_config_odbc.so: res_config_odbc.o
        $(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} ${CYG_RES_CONFIG_ODBC_LIB}
 
+res_snmp.so: res_snmp.o snmp/agent.o
+       $(CC) $(SOLINK) ${SNMP_LDFLAGS} -o $@ ${CYGSOLINK} res_snmp.o snmp/agent.o ${CYGSOLIB} ${SNMP_LDLIBS}
+
 ifneq ($(wildcard .depend),)
   include .depend
 endif
diff --git a/res/res_snmp.c b/res/res_snmp.c
new file mode 100644 (file)
index 0000000..e62e6fb
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2006 Voop as
+ * Thorsten Lockert <tholo@voop.as>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief SNMP Agent / SubAgent support for Asterisk
+ *
+ * \author Thorsten Lockert <tholo@voop.as>
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/channel.h"
+#include "asterisk/module.h"
+#include "asterisk/logger.h"
+#include "asterisk/options.h"
+
+#include "snmp/agent.h"
+
+#define        MODULE_DESCRIPTION      "SNMP [Sub]Agent for Asterisk"
+
+int res_snmp_agentx_subagent;
+int res_snmp_dont_stop;
+int res_snmp_enabled;
+
+static pthread_t thread;
+
+static int load_config(void)
+{
+    struct ast_variable *var;
+    struct ast_config *cfg;
+    char *cat;
+       
+       res_snmp_enabled = 0;
+       res_snmp_agentx_subagent = 1;
+    cfg = ast_config_load("res_snmp.conf");
+    if (cfg) {
+               cat = ast_category_browse(cfg, NULL);
+               while (cat) {
+                       var = ast_variable_browse(cfg, cat);
+
+                       if (strcasecmp(cat, "general") == 0) {
+                               while (var) {
+                                       if (strcasecmp(var->name, "subagent") == 0) {
+                                               if (ast_true(var->value))
+                                                       res_snmp_agentx_subagent = 1;
+                                               else if (ast_false(var->value))
+                                                       res_snmp_agentx_subagent = 0;
+                                               else {
+                                                       ast_log(LOG_ERROR, "Value '%s' does not evaluate to true or false.\n",
+                                                                       var->value);
+                                                       ast_config_destroy(cfg);
+                                                       return 1;
+                                               }
+                                       } else if (strcasecmp(var->name, "enabled") == 0) {
+                                               res_snmp_enabled = ast_true(var->value);
+                                       } else {
+                                               ast_log(LOG_ERROR, "Unrecognized variable '%s' in category '%s'\n",
+                                                               var->name, cat);
+                                               ast_config_destroy(cfg);
+                                               return 1;
+                                       }
+                                       var = var->next;
+                               }
+                       }
+                       else {
+                               ast_log(LOG_ERROR, "Unrecognized category '%s'\n", cat);
+                               ast_config_destroy(cfg);
+                               return 1;
+                       }
+
+                       cat = ast_category_browse(cfg, cat);
+               }
+               ast_config_destroy(cfg);
+    }
+
+    return 0;
+}
+
+int load_module(void)
+{
+    load_config();
+
+    ast_verbose(VERBOSE_PREFIX_1 "Loading [Sub]Agent Module\n");
+
+    res_snmp_dont_stop = 1;
+       if (res_snmp_enabled)
+           return ast_pthread_create(&thread, NULL, agent_thread, NULL);
+       else
+               return 0;
+}
+
+int unload_module(void)
+{
+    ast_verbose(VERBOSE_PREFIX_1 "Unloading [Sub]Agent Module\n");
+
+    res_snmp_dont_stop = 0;
+    return pthread_join(thread, NULL);
+}
+
+int reload(void)
+{
+    ast_verbose(VERBOSE_PREFIX_1 "Reloading [Sub]Agent Module\n");
+
+    res_snmp_dont_stop = 0;
+    pthread_join(thread, NULL);
+
+    load_config();
+
+    res_snmp_dont_stop = 1;
+       if (res_snmp_enabled)
+           return ast_pthread_create(&thread, NULL, agent_thread, NULL);
+       else
+               return 0;
+}
+
+int usecount(void)
+{
+    return 0;
+}
+
+char *key(void)
+{
+    return ASTERISK_GPL_KEY;
+}
+
+char *description(void)
+{
+    return MODULE_DESCRIPTION;
+}
+
+/*
+ * Local Variables:
+ * c-file-style: gnu
+ * c-basic-offset: 4
+ * c-file-offsets: ((case-label . 0))
+ * tab-width: 4
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/res/snmp/agent.c b/res/snmp/agent.c
new file mode 100644 (file)
index 0000000..740f5c1
--- /dev/null
@@ -0,0 +1,845 @@
+/*
+ * Copyright (C) 2006 Voop as
+ * Thorsten Lockert <tholo@voop.as>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief SNMP Agent / SubAgent support for Asterisk
+ *
+ * \author Thorsten Lockert <tholo@voop.as>
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+/*
+ * These conflict with ones in Asterisk header files, so
+ * get rid of  them.  They'll be back after the next few
+ * includes...
+ */
+#undef HAVE_GETLOADAVG
+#undef HAVE_STRCASESTR
+
+#include <pthread.h>
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/channel.h"
+#include "asterisk/logger.h"
+#include "asterisk/options.h"
+#include "asterisk/indications.h"
+#include "asterisk/version.h"
+#include "asterisk/pbx.h"
+
+/* Colission between Net-SNMP and Asterisk */
+#define unload_module ast_unload_module
+#include "asterisk/module.h"
+#undef unload_module
+
+#include "agent.h"
+
+/* Helper functions in Net-SNMP, header file not installed by default */
+int header_generic(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **);
+int header_simple_table(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **, int);
+int register_sysORTable(oid *, size_t, const char *);
+int unregister_sysORTable(oid *, size_t);
+
+/* Not defined in header files */
+extern char ast_config_AST_SOCKET[];
+
+/* Forward declaration */
+static void init_asterisk_mib(void);
+
+/*
+ * Anchor for all the Asterisk MIB values
+ */
+static oid asterisk_oid[] = { 1, 3, 6, 1, 4, 1, 22736, 1 };
+
+/*
+ * MIB values -- these correspond to values in the Asterisk MIB,
+ * and MUST be kept in sync with the MIB for things to work as
+ * expected.
+ */
+#define ASTVERSION                             1
+#define                ASTVERSTRING                    1
+#define                ASTVERTAG                               2
+
+#define        ASTCONFIGURATION                2
+#define                ASTCONFUPTIME                   1
+#define                ASTCONFRELOADTIME               2
+#define                ASTCONFPID                              3
+#define                ASTCONFSOCKET                   4
+
+#define        ASTMODULES                              3
+#define                ASTMODCOUNT                             1
+
+#define        ASTINDICATIONS                  4
+#define                ASTINDCOUNT                             1
+#define                ASTINDCURRENT                   2
+
+#define                ASTINDTABLE                             3
+#define                        ASTINDINDEX                             1
+#define                        ASTINDCOUNTRY                   2
+#define                        ASTINDALIAS                             3
+#define                        ASTINDDESCRIPTION               4
+
+#define        ASTCHANNELS                             5
+#define                ASTCHANCOUNT                    1
+
+#define                ASTCHANTABLE                    2
+#define                        ASTCHANINDEX                    1
+#define                        ASTCHANNAME                             2
+#define                        ASTCHANLANGUAGE                 3
+#define                        ASTCHANTYPE                             4
+#define                        ASTCHANMUSICCLASS               5
+#define                        ASTCHANBRIDGE                   6
+#define                        ASTCHANMASQ                             7
+#define                        ASTCHANMASQR                    8
+#define                        ASTCHANWHENHANGUP               9
+#define                        ASTCHANAPP                              10
+#define                        ASTCHANDATA                             11
+#define                        ASTCHANCONTEXT                  12
+#define                        ASTCHANMACROCONTEXT             13
+#define                        ASTCHANMACROEXTEN               14
+#define                        ASTCHANMACROPRI                 15
+#define                        ASTCHANEXTEN                    16
+#define                        ASTCHANPRI                              17
+#define                        ASTCHANACCOUNTCODE              18
+#define                        ASTCHANFORWARDTO                19
+#define                        ASTCHANUNIQUEID                 20
+#define                        ASTCHANCALLGROUP                21
+#define                        ASTCHANPICKUPGROUP              22
+#define                        ASTCHANSTATE                    23
+#define                        ASTCHANMUTED                    24
+#define                        ASTCHANRINGS                    25
+#define                        ASTCHANCIDDNID                  26
+#define                        ASTCHANCIDNUM                   27
+#define                        ASTCHANCIDNAME                  28
+#define                        ASTCHANCIDANI                   29
+#define                        ASTCHANCIDRDNIS                 30
+#define                        ASTCHANCIDPRES                  31
+#define                        ASTCHANCIDANI2                  32
+#define                        ASTCHANCIDTON                   33
+#define                        ASTCHANCIDTNS                   34
+#define                        ASTCHANAMAFLAGS                 35
+#define                        ASTCHANADSI                             36
+#define                        ASTCHANTONEZONE                 37
+#define                        ASTCHANHANGUPCAUSE              38
+#define                        ASTCHANVARIABLES                39
+#define                        ASTCHANFLAGS                    40
+#define                        ASTCHANTRANSFERCAP              41
+
+#define                ASTCHANTYPECOUNT                3
+
+#define                ASTCHANTYPETABLE                4
+#define                        ASTCHANTYPEINDEX                1
+#define                        ASTCHANTYPENAME                 2
+#define                        ASTCHANTYPEDESC                 3
+#define                        ASTCHANTYPEDEVSTATE             4
+#define                        ASTCHANTYPEINDICATIONS  5
+#define                        ASTCHANTYPETRANSFER             6
+#define                        ASTCHANTYPECHANNELS             7
+
+void *agent_thread(void *arg)
+{
+    ast_verbose(VERBOSE_PREFIX_2 "Starting %sAgent\n", res_snmp_agentx_subagent ? "Sub" : "");
+
+    snmp_enable_stderrlog();
+
+    if (res_snmp_agentx_subagent)
+               netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
+                                                          NETSNMP_DS_AGENT_ROLE,
+                                                          1);
+
+    init_agent("asterisk");
+
+    init_asterisk_mib();
+
+    init_snmp("asterisk");
+
+    if (!res_snmp_agentx_subagent)
+               init_master_agent();
+
+    while (res_snmp_dont_stop)
+               agent_check_and_process(1);
+
+    snmp_shutdown("asterisk");
+
+    ast_verbose(VERBOSE_PREFIX_2 "Terminating %sAgent\n",
+                               res_snmp_agentx_subagent ? "Sub" : "");
+
+    return NULL;
+}
+
+static u_char *
+ast_var_channels(struct variable *vp, oid *name, size_t *length,
+                                int exact, size_t *var_len, WriteMethod **write_method)
+{
+    static unsigned long long_ret;
+
+    if (header_generic(vp, name, length, exact, var_len, write_method))
+               return NULL;
+
+    switch (vp->magic) {
+       case ASTCHANCOUNT:
+               long_ret = ast_active_channels();
+               return (u_char *)&long_ret;
+       default:
+               break;
+    }
+    return NULL;
+}
+
+static u_char *ast_var_channels_table(struct variable *vp, oid *name, size_t *length,
+                                                                       int exact, size_t *var_len, WriteMethod **write_method)
+{
+    static unsigned long long_ret;
+    static u_char bits_ret[2];
+    static char string_ret[256];
+    struct ast_channel *chan, *bridge;
+    struct timeval tval;
+    u_char *ret;
+    int i, bit;
+
+    if (header_simple_table(vp, name, length, exact, var_len, write_method, ast_active_channels()))
+               return NULL;
+
+    i = name[*length - 1] - 1;
+    for (chan = ast_channel_walk_locked(NULL);
+                chan && i;
+                chan = ast_channel_walk_locked(chan), i--)
+               ast_mutex_unlock(&chan->lock);
+    if (chan == NULL)
+               return NULL;
+       *var_len = sizeof(long_ret);
+
+    switch (vp->magic) {
+       case ASTCHANINDEX:
+               long_ret = name[*length - 1];
+               ret = (u_char *)&long_ret;
+               break;
+       case ASTCHANNAME:
+               if (!ast_strlen_zero(chan->name)) {
+                       strncpy(string_ret, chan->name, sizeof(string_ret));
+                       string_ret[sizeof(string_ret) - 1] = '\0';
+                       *var_len = strlen(string_ret);
+                       ret = (u_char *)string_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANLANGUAGE:
+               if (!ast_strlen_zero(chan->language)) {
+                       strncpy(string_ret, chan->language, sizeof(string_ret));
+                       string_ret[sizeof(string_ret) - 1] = '\0';
+                       *var_len = strlen(string_ret);
+                       ret = (u_char *)string_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANTYPE:
+               strncpy(string_ret, chan->tech->type, sizeof(string_ret));
+               string_ret[sizeof(string_ret) - 1] = '\0';
+               *var_len = strlen(string_ret);
+               ret = (u_char *)string_ret;
+               break;
+       case ASTCHANMUSICCLASS:
+               if (!ast_strlen_zero(chan->musicclass)) {
+                       strncpy(string_ret, chan->musicclass, sizeof(string_ret));
+                       string_ret[sizeof(string_ret) - 1] = '\0';
+                       *var_len = strlen(string_ret);
+                       ret = (u_char *)string_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANBRIDGE:
+               if ((bridge = ast_bridged_channel(chan)) != NULL) {
+                       strncpy(string_ret, bridge->name, sizeof(string_ret));
+                       string_ret[sizeof(string_ret) - 1] = '\0';
+                       *var_len = strlen(string_ret);
+                       ret = (u_char *)string_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANMASQ:
+               if (chan->masq && !ast_strlen_zero(chan->masq->name)) {
+                       strncpy(string_ret, chan->masq->name, sizeof(string_ret));
+                       string_ret[sizeof(string_ret) - 1] = '\0';
+                       *var_len = strlen(string_ret);
+                       ret = (u_char *)string_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANMASQR:
+               if (chan->masqr && !ast_strlen_zero(chan->masqr->name)) {
+                       strncpy(string_ret, chan->masqr->name, sizeof(string_ret));
+                       string_ret[sizeof(string_ret) - 1] = '\0';
+                       *var_len = strlen(string_ret);
+                       ret = (u_char *)string_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANWHENHANGUP:
+               if (chan->whentohangup) {
+                       gettimeofday(&tval, NULL);
+                       long_ret = difftime(chan->whentohangup, tval.tv_sec) * 100 - tval.tv_usec / 10000;
+                       ret= (u_char *)&long_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANAPP:
+               if (chan->appl) {
+                       strncpy(string_ret, chan->appl, sizeof(string_ret));
+                       string_ret[sizeof(string_ret) - 1] = '\0';
+                       *var_len = strlen(string_ret);
+                       ret = (u_char *)string_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANDATA:
+               if (chan->data) {
+                       strncpy(string_ret, chan->data, sizeof(string_ret));
+                       string_ret[sizeof(string_ret) - 1] = '\0';
+                       *var_len = strlen(string_ret);
+                       ret = (u_char *)string_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANCONTEXT:
+               strncpy(string_ret, chan->context, sizeof(string_ret));
+               string_ret[sizeof(string_ret) - 1] = '\0';
+               *var_len = strlen(string_ret);
+               ret = (u_char *)string_ret;
+               break;
+       case ASTCHANMACROCONTEXT:
+               strncpy(string_ret, chan->macrocontext, sizeof(string_ret));
+               string_ret[sizeof(string_ret) - 1] = '\0';
+               *var_len = strlen(string_ret);
+               ret = (u_char *)string_ret;
+               break;
+       case ASTCHANMACROEXTEN:
+               strncpy(string_ret, chan->macroexten, sizeof(string_ret));
+               string_ret[sizeof(string_ret) - 1] = '\0';
+               *var_len = strlen(string_ret);
+               ret = (u_char *)string_ret;
+               break;
+       case ASTCHANMACROPRI:
+               long_ret = chan->macropriority;
+               ret = (u_char *)&long_ret;
+               break;
+       case ASTCHANEXTEN:
+               strncpy(string_ret, chan->exten, sizeof(string_ret));
+               string_ret[sizeof(string_ret) - 1] = '\0';
+               *var_len = strlen(string_ret);
+               ret = (u_char *)string_ret;
+               break;
+       case ASTCHANPRI:
+               long_ret = chan->priority;
+               ret = (u_char *)&long_ret;
+               break;
+       case ASTCHANACCOUNTCODE:
+               if (!ast_strlen_zero(chan->accountcode)) {
+                       strncpy(string_ret, chan->accountcode, sizeof(string_ret));
+                       string_ret[sizeof(string_ret) - 1] = '\0';
+                       *var_len = strlen(string_ret);
+                       ret = (u_char *)string_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANFORWARDTO:
+               if (!ast_strlen_zero(chan->call_forward)) {
+                       strncpy(string_ret, chan->call_forward, sizeof(string_ret));
+                       string_ret[sizeof(string_ret) - 1] = '\0';
+                       *var_len = strlen(string_ret);
+                       ret = (u_char *)string_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANUNIQUEID:
+               strncpy(string_ret, chan->uniqueid, sizeof(string_ret));
+               string_ret[sizeof(string_ret) - 1] = '\0';
+               *var_len = strlen(string_ret);
+               ret = (u_char *)string_ret;
+               break;
+       case ASTCHANCALLGROUP:
+               long_ret = chan->callgroup;
+               ret = (u_char *)&long_ret;
+               break;
+       case ASTCHANPICKUPGROUP:
+               long_ret = chan->pickupgroup;
+               ret = (u_char *)&long_ret;
+               break;
+       case ASTCHANSTATE:
+               long_ret = chan->_state & 0xffff;
+               ret = (u_char *)&long_ret;
+               break;
+       case ASTCHANMUTED:
+               long_ret = chan->_state & AST_STATE_MUTE ? 1 : 2;
+               ret = (u_char *)&long_ret;
+               break;
+       case ASTCHANRINGS:
+               long_ret = chan->rings;
+               ret = (u_char *)&long_ret;
+               break;
+       case ASTCHANCIDDNID:
+               if (chan->cid.cid_dnid) {
+                       strncpy(string_ret, chan->cid.cid_dnid, sizeof(string_ret));
+                       string_ret[sizeof(string_ret) - 1] = '\0';
+                       *var_len = strlen(string_ret);
+                       ret = (u_char *)string_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANCIDNUM:
+               if (chan->cid.cid_num) {
+                       strncpy(string_ret, chan->cid.cid_num, sizeof(string_ret));
+                       string_ret[sizeof(string_ret) - 1] = '\0';
+                       *var_len = strlen(string_ret);
+                       ret = (u_char *)string_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANCIDNAME:
+               if (chan->cid.cid_name) {
+                       strncpy(string_ret, chan->cid.cid_name, sizeof(string_ret));
+                       string_ret[sizeof(string_ret) - 1] = '\0';
+                       *var_len = strlen(string_ret);
+                       ret = (u_char *)string_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANCIDANI:
+               if (chan->cid.cid_ani) {
+                       strncpy(string_ret, chan->cid.cid_ani, sizeof(string_ret));
+                       string_ret[sizeof(string_ret) - 1] = '\0';
+                       *var_len = strlen(string_ret);
+                       ret = (u_char *)string_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANCIDRDNIS:
+               if (chan->cid.cid_rdnis) {
+                       strncpy(string_ret, chan->cid.cid_rdnis, sizeof(string_ret));
+                       string_ret[sizeof(string_ret) - 1] = '\0';
+                       *var_len = strlen(string_ret);
+                       ret = (u_char *)string_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANCIDPRES:
+               long_ret = chan->cid.cid_pres;
+               ret = (u_char *)&long_ret;
+               break;
+       case ASTCHANCIDANI2:
+               long_ret = chan->cid.cid_ani2;
+               ret = (u_char *)&long_ret;
+               break;
+       case ASTCHANCIDTON:
+               long_ret = chan->cid.cid_ton;
+               ret = (u_char *)&long_ret;
+               break;
+       case ASTCHANCIDTNS:
+               long_ret = chan->cid.cid_tns;
+               ret = (u_char *)&long_ret;
+               break;
+       case ASTCHANAMAFLAGS:
+               long_ret = chan->amaflags;
+               ret = (u_char *)&long_ret;
+               break;
+       case ASTCHANADSI:
+               long_ret = chan->adsicpe;
+               ret = (u_char *)&long_ret;
+               break;
+       case ASTCHANTONEZONE:
+               if (chan->zone) {
+                       strncpy(string_ret, chan->zone->country, sizeof(string_ret));
+                       string_ret[sizeof(string_ret) - 1] = '\0';
+                       *var_len = strlen(string_ret);
+                       ret = (u_char *)string_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANHANGUPCAUSE:
+               long_ret = chan->hangupcause;
+               ret = (u_char *)&long_ret;
+               break;
+       case ASTCHANVARIABLES:
+               if (pbx_builtin_serialize_variables(chan, string_ret, sizeof(string_ret))) {
+                       *var_len = strlen(string_ret);
+                       ret = (u_char *)string_ret;
+               }
+               else
+                       ret = NULL;
+               break;
+       case ASTCHANFLAGS:
+               bits_ret[0] = 0;
+               for (bit = 0; bit < 8; bit++)
+                       bits_ret[0] |= ((chan->flags & (1 << bit)) >> bit) << (7 - bit);
+               bits_ret[1] = 0;
+               for (bit = 0; bit < 8; bit++)
+                       bits_ret[1] |= (((chan->flags >> 8) & (1 << bit)) >> bit) << (7 - bit);
+               *var_len = 2;
+               ret = bits_ret;
+               break;
+       case ASTCHANTRANSFERCAP:
+               long_ret = chan->transfercapability;
+               ret = (u_char *)&long_ret;
+               break;
+       default:
+               ret = NULL;
+               break;
+    }
+    ast_mutex_unlock(&chan->lock);
+    return ret;
+}
+
+static u_char *ast_var_channel_types(struct variable *vp, oid *name, size_t *length,
+                                                                  int exact, size_t *var_len, WriteMethod **write_method)
+{
+    static unsigned long long_ret;
+       struct ast_variable *channel_types, *next;
+
+    if (header_generic(vp, name, length, exact, var_len, write_method))
+               return NULL;
+
+    switch (vp->magic) {
+       case ASTCHANTYPECOUNT:
+               long_ret = 0;
+               for (channel_types = next = ast_channeltype_list(); next; next = next->next) {
+                       long_ret++;
+               }
+               ast_variables_destroy(channel_types);
+               return (u_char *)&long_ret;
+       default:
+               break;
+    }
+    return NULL;
+}
+
+static u_char *ast_var_channel_types_table(struct variable *vp, oid *name, size_t *length,
+                                                                               int exact, size_t *var_len, WriteMethod **write_method)
+{
+       const struct ast_channel_tech *tech = NULL;
+       struct ast_variable *channel_types, *next;
+    static unsigned long long_ret;
+    struct ast_channel *chan;
+    u_long i;
+
+    if (header_simple_table(vp, name, length, exact, var_len, write_method, -1))
+               return NULL;
+
+       channel_types = ast_channeltype_list();
+       for (i = 1, next = channel_types; next && i != name[*length - 1]; next = next->next, i++)
+               ;
+       if (next != NULL)
+               tech = ast_get_channel_tech(next->name);
+       ast_variables_destroy(channel_types);
+    if (next == NULL || tech == NULL)
+               return NULL;
+    
+    switch (vp->magic) {
+       case ASTCHANTYPEINDEX:
+               long_ret = name[*length - 1];
+               return (u_char *)&long_ret;
+       case ASTCHANTYPENAME:
+               *var_len = strlen(tech->type);
+               return (u_char *)tech->type;
+       case ASTCHANTYPEDESC:
+               *var_len = strlen(tech->description);
+               return (u_char *)tech->description;
+       case ASTCHANTYPEDEVSTATE:
+               long_ret = tech->devicestate ? 1 : 2;
+               return (u_char *)&long_ret;
+       case ASTCHANTYPEINDICATIONS:
+               long_ret = tech->indicate ? 1 : 2;
+               return (u_char *)&long_ret;
+       case ASTCHANTYPETRANSFER:
+               long_ret = tech->transfer ? 1 : 2;
+               return (u_char *)&long_ret;
+       case ASTCHANTYPECHANNELS:
+               long_ret = 0;
+               for (chan = ast_channel_walk_locked(NULL); chan; chan = ast_channel_walk_locked(chan)) {
+                       ast_mutex_unlock(&chan->lock);
+                       if (chan->tech == tech)
+                               long_ret++;
+               }
+               return (u_char *)&long_ret;
+       default:
+               break;
+    }
+    return NULL;
+}
+
+static u_char *ast_var_Config(struct variable *vp, oid *name, size_t *length,
+                                                        int exact, size_t *var_len, WriteMethod **write_method)
+{
+    static unsigned long long_ret;
+    struct timeval tval;
+
+    if (header_generic(vp, name, length, exact, var_len, write_method))
+               return NULL;
+
+    switch (vp->magic) {
+       case ASTCONFUPTIME:
+               gettimeofday(&tval, NULL);
+               long_ret = difftime(tval.tv_sec, ast_startuptime) * 100 + tval.tv_usec / 10000;
+               return (u_char *)&long_ret;
+       case ASTCONFRELOADTIME:
+               gettimeofday(&tval, NULL);
+               if (ast_lastreloadtime)
+                       long_ret = difftime(tval.tv_sec, ast_lastreloadtime) * 100 + tval.tv_usec / 10000;
+               else
+                       long_ret = difftime(tval.tv_sec, ast_startuptime) * 100 + tval.tv_usec / 10000;
+               return (u_char *)&long_ret;
+       case ASTCONFPID:
+               long_ret = getpid();
+               return (u_char *)&long_ret;
+       case ASTCONFSOCKET:
+               *var_len = strlen(ast_config_AST_SOCKET);
+               return (u_char *)ast_config_AST_SOCKET;
+       default:
+               break;
+    }
+    return NULL;
+}
+
+static u_char *ast_var_indications(struct variable *vp, oid *name, size_t *length,
+                                                                 int exact, size_t *var_len, WriteMethod **write_method)
+{
+    static unsigned long long_ret;
+    struct tone_zone *tz;
+
+    if (header_generic(vp, name, length, exact, var_len, write_method))
+               return NULL;
+
+    switch (vp->magic) {
+       case ASTINDCOUNT:
+               if (ast_mutex_lock(&tzlock)) {
+                       ast_log(LOG_WARNING, "Unable to lock tone_zones list\n");
+                       snmp_log(LOG_ERR, "Unable to lock tone_zones list in ast_var_indications\n");
+                       return NULL;
+               }
+               long_ret = 0;
+               for (tz = tone_zones; tz; tz = tz->next)
+                       long_ret++;
+               ast_mutex_unlock(&tzlock);
+
+               return (u_char *)&long_ret;
+       case ASTINDCURRENT:
+               tz = ast_get_indication_zone(NULL);
+               if (tz) {
+                       *var_len = strlen(tz->country);
+                       return (u_char *)tz->country;
+               }
+               *var_len = 0;
+               return NULL;
+       default:
+               break;
+    }
+    return NULL;
+}
+
+static u_char *ast_var_indications_table(struct variable *vp, oid *name, size_t *length,
+                                                                          int exact, size_t *var_len, WriteMethod **write_method)
+{
+    static unsigned long long_ret;
+    struct tone_zone *tz;
+    int i;
+
+    if (header_simple_table(vp, name, length, exact, var_len, write_method, -1))
+               return NULL;
+
+    if (ast_mutex_lock(&tzlock)) {
+               ast_log(LOG_WARNING, "Unable to lock tone_zones list\n");
+               snmp_log(LOG_ERR, "Unable to lock tone_zones list in ast_var_indications_table\n");
+               return NULL;
+    }
+    i = name[*length - 1] - 1;
+    for (tz = tone_zones; tz && i; tz = tz->next)
+               i--;
+    ast_mutex_unlock(&tzlock);
+    if (tz == NULL)
+               return NULL;
+
+    switch (vp->magic) {
+       case ASTINDINDEX:
+               long_ret = name[*length - 1];
+               return (u_char *)&long_ret;
+       case ASTINDCOUNTRY:
+               *var_len = strlen(tz->country);
+               return (u_char *)tz->country;
+       case ASTINDALIAS:
+               if (tz->alias) {
+                       *var_len = strlen(tz->alias);
+                       return (u_char *)tz->alias;
+               }
+               return NULL;
+       case ASTINDDESCRIPTION:
+               *var_len = strlen(tz->description);
+               return (u_char *)tz->description;
+       default:
+               break;
+    }
+    return NULL;
+}
+
+static int countmodule(const char *mod, const char *desc, int use, const char *like)
+{
+    return 1;
+}
+
+static u_char *ast_var_Modules(struct variable *vp, oid *name, size_t *length,
+                                                         int exact, size_t *var_len, WriteMethod **write_method)
+{
+    static unsigned long long_ret;
+
+    if (header_generic(vp, name, length, exact, var_len, write_method))
+               return NULL;
+
+    switch (vp->magic) {
+       case ASTMODCOUNT:
+               long_ret = ast_update_module_list(countmodule, NULL);
+               return (u_char *)&long_ret;
+       default:
+               break;
+    }
+    return NULL;
+}
+
+static u_char *ast_var_Version(struct variable *vp, oid *name, size_t *length,
+                                                         int exact, size_t *var_len, WriteMethod **write_method)
+{
+    static unsigned long long_ret;
+
+    if (header_generic(vp, name, length, exact, var_len, write_method))
+               return NULL;
+
+    switch (vp->magic) {
+       case ASTVERSTRING:
+               *var_len = strlen(ASTERISK_VERSION);
+               return (u_char *)ASTERISK_VERSION;
+       case ASTVERTAG:
+               long_ret = ASTERISK_VERSION_NUM;
+               return (u_char *)&long_ret;
+       default:
+               break;
+    }
+    return NULL;
+}
+
+static int term_asterisk_mib(int majorID, int minorID, void *serverarg, void *clientarg)
+{
+    unregister_sysORTable(asterisk_oid, OID_LENGTH(asterisk_oid));
+    return 0;
+}
+
+static void init_asterisk_mib(void)
+{
+    static struct variable4 asterisk_vars[] = {
+               {ASTVERSTRING,           ASN_OCTET_STR, RONLY, ast_var_Version,             2, {ASTVERSION, ASTVERSTRING}},
+               {ASTVERTAG,              ASN_UNSIGNED,  RONLY, ast_var_Version,             2, {ASTVERSION, ASTVERTAG}},
+               {ASTCONFUPTIME,          ASN_TIMETICKS, RONLY, ast_var_Config,              2, {ASTCONFIGURATION, ASTCONFUPTIME}},
+               {ASTCONFRELOADTIME,      ASN_TIMETICKS, RONLY, ast_var_Config,              2, {ASTCONFIGURATION, ASTCONFRELOADTIME}},
+               {ASTCONFPID,             ASN_INTEGER,   RONLY, ast_var_Config,              2, {ASTCONFIGURATION, ASTCONFPID}},
+               {ASTCONFSOCKET,          ASN_OCTET_STR, RONLY, ast_var_Config,              2, {ASTCONFIGURATION, ASTCONFSOCKET}},
+               {ASTMODCOUNT,            ASN_INTEGER,   RONLY, ast_var_Modules ,            2, {ASTMODULES, ASTMODCOUNT}},
+               {ASTINDCOUNT,            ASN_INTEGER,   RONLY, ast_var_indications,         2, {ASTINDICATIONS, ASTINDCOUNT}},
+               {ASTINDCURRENT,          ASN_OCTET_STR, RONLY, ast_var_indications,         2, {ASTINDICATIONS, ASTINDCURRENT}},
+               {ASTINDINDEX,            ASN_INTEGER,   RONLY, ast_var_indications_table,   4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDINDEX}},
+               {ASTINDCOUNTRY,          ASN_OCTET_STR, RONLY, ast_var_indications_table,   4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDCOUNTRY}},
+               {ASTINDALIAS,            ASN_OCTET_STR, RONLY, ast_var_indications_table,   4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDALIAS}},
+               {ASTINDDESCRIPTION,      ASN_OCTET_STR, RONLY, ast_var_indications_table,   4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDDESCRIPTION}},
+               {ASTCHANCOUNT,           ASN_INTEGER,   RONLY, ast_var_channels,            2, {ASTCHANNELS, ASTCHANCOUNT}},
+               {ASTCHANINDEX,           ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANINDEX}},
+               {ASTCHANNAME,            ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANNAME}},
+               {ASTCHANLANGUAGE,        ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANLANGUAGE}},
+               {ASTCHANTYPE,            ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTYPE}},
+               {ASTCHANMUSICCLASS,      ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMUSICCLASS}},
+               {ASTCHANBRIDGE,          ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANBRIDGE}},
+               {ASTCHANMASQ,            ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMASQ}},
+               {ASTCHANMASQR,           ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMASQR}},
+               {ASTCHANWHENHANGUP,      ASN_TIMETICKS, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANWHENHANGUP}},
+               {ASTCHANAPP,             ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANAPP}},
+               {ASTCHANDATA,            ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANDATA}},
+               {ASTCHANCONTEXT,         ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCONTEXT}},
+               {ASTCHANMACROCONTEXT,    ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROCONTEXT}},
+               {ASTCHANMACROEXTEN,      ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROEXTEN}},
+               {ASTCHANMACROPRI,        ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROPRI}},
+               {ASTCHANEXTEN,           ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANEXTEN}},
+               {ASTCHANPRI,             ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANPRI}},
+               {ASTCHANACCOUNTCODE,     ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANACCOUNTCODE}},
+               {ASTCHANFORWARDTO,       ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANFORWARDTO}},
+               {ASTCHANUNIQUEID,        ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANUNIQUEID}},
+               {ASTCHANCALLGROUP,       ASN_UNSIGNED,  RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCALLGROUP}},
+               {ASTCHANPICKUPGROUP,     ASN_UNSIGNED,  RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANPICKUPGROUP}},
+               {ASTCHANSTATE,           ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANSTATE}},
+               {ASTCHANMUTED,           ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMUTED}},
+               {ASTCHANRINGS,           ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANRINGS}},
+               {ASTCHANCIDDNID,         ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDDNID}},
+               {ASTCHANCIDNUM,          ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDNUM}},
+               {ASTCHANCIDNAME,         ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDNAME}},
+               {ASTCHANCIDANI,          ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDANI}},
+               {ASTCHANCIDRDNIS,        ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDRDNIS}},
+               {ASTCHANCIDPRES,         ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDPRES}},
+               {ASTCHANCIDANI2,         ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDANI2}},
+               {ASTCHANCIDTON,          ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDTON}},
+               {ASTCHANCIDTNS,          ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDTNS}},
+               {ASTCHANAMAFLAGS,        ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANAMAFLAGS}},
+               {ASTCHANADSI,            ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANADSI}},
+               {ASTCHANTONEZONE,        ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTONEZONE}},
+               {ASTCHANHANGUPCAUSE,     ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANHANGUPCAUSE}},
+               {ASTCHANVARIABLES,       ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANVARIABLES}},
+               {ASTCHANFLAGS,           ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANFLAGS}},
+               {ASTCHANTRANSFERCAP,     ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTRANSFERCAP}},
+               {ASTCHANTYPECOUNT,       ASN_INTEGER,   RONLY, ast_var_channel_types,       2, {ASTCHANNELS, ASTCHANTYPECOUNT}},
+               {ASTCHANTYPEINDEX,       ASN_INTEGER,   RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEINDEX}},
+               {ASTCHANTYPENAME,        ASN_OCTET_STR, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPENAME}},
+               {ASTCHANTYPEDESC,        ASN_OCTET_STR, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEDESC}},
+               {ASTCHANTYPEDEVSTATE,    ASN_INTEGER,   RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEDEVSTATE}},
+               {ASTCHANTYPEINDICATIONS, ASN_INTEGER,   RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEINDICATIONS}},
+               {ASTCHANTYPETRANSFER,    ASN_INTEGER,   RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPETRANSFER}},
+               {ASTCHANTYPECHANNELS,    ASN_GAUGE,     RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPECHANNELS}},
+    };
+
+    register_sysORTable(asterisk_oid, OID_LENGTH(asterisk_oid),
+                       "ASTERISK-MIB implementation for Asterisk.");
+
+    REGISTER_MIB("res_snmp", asterisk_vars, variable4, asterisk_oid);
+
+    snmp_register_callback(SNMP_CALLBACK_LIBRARY,
+                          SNMP_CALLBACK_SHUTDOWN,
+                          term_asterisk_mib, NULL);
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 4
+ * c-file-offsets: ((case-label . 0))
+ * tab-width: 4
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/res/snmp/agent.h b/res/snmp/agent.h
new file mode 100644 (file)
index 0000000..21389d6
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2006 Voop as
+ * Thorsten Lockert <tholo@voop.as>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief SNMP Agent / SubAgent support for Asterisk
+ *
+ * \author Thorsten Lockert <tholo@voop.as>
+ */
+
+/*!
+ * \internal
+ * \brief Thread running the SNMP Agent or Subagent
+ * \param Not used -- required by pthread_create
+ * \return A pointer with return status -- not used
+ *
+ * This represent the main thread of the SNMP [sub]agent, and
+ * will initialize SNMP and loop, processing requests until
+ * termination is requested by resetting the flag in
+ * \ref res_snmp_dontStop.
+ */
+void   *agent_thread(void *);
+
+/*!
+ * \internal
+ * Flag saying whether we run as a Subagent or full Agent
+ */
+extern int res_snmp_agentx_subagent;
+
+/*!
+ * \internal
+ * Flag stating the agent thread should not terminate
+ */
+extern int res_snmp_dont_stop;