summaryrefslogtreecommitdiff
path: root/contrib/bsnmp/snmp_ntp
diff options
context:
space:
mode:
authorHartmut Brandt <harti@FreeBSD.org>2005-04-26 16:43:22 +0000
committerHartmut Brandt <harti@FreeBSD.org>2005-04-26 16:43:22 +0000
commitd7eb6b4714d872b3db1975c49bda81474b352e7f (patch)
tree6014070dbafff7c4eef049f6811fe88a34589a73 /contrib/bsnmp/snmp_ntp
parent94caccb35748458a2c8bdb15a8e700d5e384ae14 (diff)
downloadsrc-test2-d7eb6b4714d872b3db1975c49bda81474b352e7f.tar.gz
src-test2-d7eb6b4714d872b3db1975c49bda81474b352e7f.zip
Notes
Diffstat (limited to 'contrib/bsnmp/snmp_ntp')
-rw-r--r--contrib/bsnmp/snmp_ntp/BEGEMOT-NTP-MIB.txt117
-rw-r--r--contrib/bsnmp/snmp_ntp/NTP-MIB.txt627
-rw-r--r--contrib/bsnmp/snmp_ntp/NTP-PROXY-MIB.txt616
-rw-r--r--contrib/bsnmp/snmp_ntp/ntp_tree.def122
-rw-r--r--contrib/bsnmp/snmp_ntp/snmp_ntp.c1592
5 files changed, 3074 insertions, 0 deletions
diff --git a/contrib/bsnmp/snmp_ntp/BEGEMOT-NTP-MIB.txt b/contrib/bsnmp/snmp_ntp/BEGEMOT-NTP-MIB.txt
new file mode 100644
index 000000000000..c5a449505c8a
--- /dev/null
+++ b/contrib/bsnmp/snmp_ntp/BEGEMOT-NTP-MIB.txt
@@ -0,0 +1,117 @@
+--
+-- Copyright (c) 2005
+-- Hartmut Brandt
+-- All rights reserved.
+--
+-- Author: Harti Brandt <harti@freebsd.org>
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions
+-- are met:
+-- 1. Redistributions of source code must retain the above copyright
+-- notice, this list of conditions and the following disclaimer.
+-- 2. Redistributions in binary form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+-- ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+-- SUCH DAMAGE.
+--
+-- $Begemot: bsnmp/snmp_ntp/BEGEMOT-NTP-MIB.txt,v 1.2 2005/04/26 13:38:01 brandt_h Exp $
+--
+-- Private MIB for NTP module.
+--
+BEGEMOT-NTP-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+ MODULE-IDENTITY, OBJECT-TYPE, TimeTicks, Unsigned32, Counter64
+ FROM SNMPv2-SMI
+ begemot
+ FROM BEGEMOT-MIB;
+
+begemotNtp MODULE-IDENTITY
+ LAST-UPDATED "200503210000Z"
+ ORGANIZATION "German Aerospace Center"
+ CONTACT-INFO
+ " Hartmut Brandt
+
+ Postal: German Aerospace Center
+ Oberpfaffenhofen
+ 82234 Wessling
+ Germany
+
+ Fax: +49 8153 28 2843
+
+ E-mail: harti@freebsd.org"
+ DESCRIPTION
+ "The MIB for the NTP control module for SNMP."
+ ::= { begemot 201 }
+
+begemotNtpObjects OBJECT IDENTIFIER ::= { begemotNtp 1 }
+
+begemotNtpHost OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The name of the host where the NTP daemon is running that
+ is to be connected."
+ ::= { begemotNtpObjects 1 }
+
+begemotNtpPort OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The port of the host where the NTP daemon is running that
+ is to be connected."
+ ::= { begemotNtpObjects 2 }
+
+begemotNtpTimeout OBJECT-TYPE
+ SYNTAX TimeTicks
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ "The number of ticks to wait for the response from the NTP
+ daemon to complete."
+ ::= { begemotNtpObjects 3 }
+
+begemotNtpDebug OBJECT-TYPE
+ SYNTAX Unsigned32
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ "Debug flags. The following flags are currently used:
+
+ 0x01 - produce a dump of all received/sent NTP packets.
+ 0x02 - print the variable names and values return by the daemon
+
+ Other bits are ignored."
+ ::= { begemotNtpObjects 4 }
+
+begemotNtpJitter OBJECT-TYPE
+ SYNTAX Counter64
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Current jitter in seconds multiplied by 2^32."
+ ::= { begemotNtpObjects 5 }
+
+begemotNtpStability OBJECT-TYPE
+ SYNTAX Counter64
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Current stability in ppm multiplied by 2^32."
+ ::= { begemotNtpObjects 6 }
+
+END
diff --git a/contrib/bsnmp/snmp_ntp/NTP-MIB.txt b/contrib/bsnmp/snmp_ntp/NTP-MIB.txt
new file mode 100644
index 000000000000..ef5147076aa0
--- /dev/null
+++ b/contrib/bsnmp/snmp_ntp/NTP-MIB.txt
@@ -0,0 +1,627 @@
+--
+-- NTP MIB, Revision 0.2, 7/25/97
+--
+
+NTP-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+ Integer32, IpAddress, MODULE-IDENTITY, OBJECT-TYPE, Unsigned32,
+ enterprises
+ FROM SNMPv2-SMI
+
+ TEXTUAL-CONVENTION, TruthValue
+ FROM SNMPv2-TC;
+
+ntpMIB MODULE-IDENTITY
+ LAST-UPDATED "199707251530Z"
+ ORGANIZATION
+ "University of Delaware"
+ CONTACT-INFO
+ "Adarsh Sethi
+ Department of Computer & Information Sciences
+ University of Delaware
+ Newark, DE 19716
+ Tel: +1 302 831 1945
+ E-mail: sethi@cis.udel.edu
+
+ David Mills
+ Department of Electrical Engineering
+ University of Delaware
+ Newark, DE 19716
+ Tel: +1 302 831 ????
+ E-mail: mills@ee.udel.edu"
+ DESCRIPTION
+ "This MIB module defines a MIB which provides mechanisms to
+ monitor and control an NTP server."
+ ::= { udel 3 }
+
+--
+-- Position within the OID hierarchy of this MIB:
+--
+udel OBJECT IDENTIFIER
+ ::= { enterprises 1277 }
+
+--
+-- The various groups defined within this MIB definition:
+--
+ntpSystem OBJECT IDENTIFIER
+ ::= { ntpMIB 1 }
+
+ntpPeers OBJECT IDENTIFIER
+ ::= { ntpMIB 2 }
+
+ntpFilter OBJECT IDENTIFIER
+ ::= { ntpMIB 3 }
+
+--
+-- Textual conventions:
+--
+
+NTPTimeStamp ::= TEXTUAL-CONVENTION
+ DISPLAY-HINT "4x.4x"
+ STATUS current
+ DESCRIPTION
+ ""
+ SYNTAX OCTET STRING (SIZE(8))
+
+NTPLeapIndicator ::= TEXTUAL-CONVENTION
+ STATUS current
+ DESCRIPTION
+ ""
+ SYNTAX INTEGER {
+ noWarning(0),
+ addSecond(1),
+ subtractSecond(2),
+ alarm(3) }
+
+--
+-- System Group
+--
+
+ntpSysLeap OBJECT-TYPE
+ SYNTAX NTPLeapIndicator
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " two-bit code warning of an impending leap
+ second to be inserted in the NTP timescale."
+ ::= { ntpSystem 1 }
+
+ntpSysStratum OBJECT-TYPE
+ SYNTAX Integer32 (0..255)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " indicating the stratum of the local clock.
+ 0, unspecified
+ 1, primary reference (e.g.,, calibrated atomic clock,
+ radio clock)
+ 2-255, secondary reference (via NTP)"
+ ::= { ntpSystem 2 }
+
+ntpSysPrecision OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "signed integer indicating the precision
+ of the various clocks, in seconds to the nearest power
+ of two."
+ ::= { ntpSystem 3 }
+
+ntpSysRootDelay OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "the total roundtrip delay to the primary
+ reference source at the root of the synchronization
+ subnet, in seconds"
+ ::= { ntpSystem 4 }
+
+ntpSysRootDispersion OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "the maximum error relative to the primary
+ reference source at the root of the synchronization
+ subnet, in seconds. Only positive values greater
+ than zero are possible"
+ ::= { ntpSystem 5 }
+
+ntpSysRefId OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " the particular reference clock. In the case of
+ stratum 0 (unspecified) or stratum 1 (primary reference
+ source), this is a four-octet, left-justified,zero-padded
+ ASCII string.In the case of stratum 2 and greater (secondary
+ reference) this is the four-octet Internet address of the
+ peer selected for synchronization."
+ ::= { ntpSystem 6 }
+
+ntpSysRefTime OBJECT-TYPE
+ SYNTAX NTPTimeStamp
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " the local time when the local clock was last
+ updated. If the local clock has neverbeen synchronized,
+ the value is zero."
+ ::= { ntpSystem 7 }
+
+ntpSysPoll OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " the minimum interval between transmitted
+ messages, in seconds as a power of two. For instance,
+ a value of six indicates a minimum interval of 64 seconds."
+ ::= { ntpSystem 8 }
+
+ntpSysPeer OBJECT-TYPE
+ SYNTAX Unsigned32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " the current synchronization source. Usually
+ this will be a pointer to a structure containing the peer
+ variables. The special value NULL indicates there is no
+ currently valid synchronization source."
+ ::= { ntpSystem 9 }
+
+ntpSysPhase OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpSystem 10 }
+
+ntpSysFreq OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpSystem 11 }
+
+ntpSysError OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpSystem 12 }
+
+ntpSysClock OBJECT-TYPE
+ SYNTAX NTPTimeStamp
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "the current local time. Local time is derived
+ from the hardware clock of the particular machine and
+ increments at intervals depending on the design used."
+ ::= { ntpSystem 13 }
+
+ntpSysSystem OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " the type of the local Operating System"
+ ::= { ntpSystem 14 }
+
+ntpSysProcessor OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " the type of the local Processor"
+ ::= { ntpSystem 15 }
+
+--
+-- Peers Group
+--
+
+--
+-- Peer Variables Table
+--
+
+ntpPeersVarTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF NtpPeersVarEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpPeers 1 }
+
+ntpPeersVarEntry OBJECT-TYPE
+ SYNTAX NtpPeersVarEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ INDEX { ntpPeersAssocId }
+ ::= { ntpPeersVarTable 1 }
+
+NtpPeersVarEntry ::= SEQUENCE {
+ ntpPeersAssocId Unsigned32,
+ ntpPeersConfigured TruthValue,
+ ntpPeersPeerAddress IpAddress,
+ ntpPeersPeerPort Unsigned32,
+ ntpPeersHostAddress IpAddress,
+ ntpPeersHostPort Unsigned32,
+ ntpPeersLeap NTPLeapIndicator,
+ ntpPeersMode INTEGER,
+ ntpPeersStratum Integer32,
+ ntpPeersPeerPoll Integer32,
+ ntpPeersHostPoll Integer32,
+ ntpPeersPrecision Integer32,
+ ntpPeersRootDelay OCTET STRING,
+ ntpPeersRootDispersion OCTET STRING,
+ ntpPeersRefId OCTET STRING,
+ ntpPeersRefTime NTPTimeStamp,
+ ntpPeersOrgTime NTPTimeStamp,
+ ntpPeersReceiveTime NTPTimeStamp,
+ ntpPeersTransmitTime NTPTimeStamp,
+ ntpPeersUpdateTime NTPTimeStamp,
+ ntpPeersReach Unsigned32,
+ ntpPeersTimer Integer32,
+ ntpPeersOffset OCTET STRING,
+ ntpPeersDelay OCTET STRING,
+ ntpPeersDispersion OCTET STRING
+}
+
+ntpPeersAssocId OBJECT-TYPE
+ SYNTAX Unsigned32
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpPeersVarEntry 1 }
+
+ntpPeersConfigured OBJECT-TYPE
+ SYNTAX TruthValue
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " This is a bit indicating that the association
+ was created from configuration information and should not
+ be demobilized if the peer becomes unreachable."
+ ::= { ntpPeersVarEntry 2 }
+
+ntpPeersPeerAddress OBJECT-TYPE
+ SYNTAX IpAddress
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " the Internet address of the peer"
+ ::= { ntpPeersVarEntry 3 }
+
+ntpPeersPeerPort OBJECT-TYPE
+ SYNTAX Unsigned32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " 16-bit port number of the peer."
+ ::= { ntpPeersVarEntry 4 }
+
+ntpPeersHostAddress OBJECT-TYPE
+ SYNTAX IpAddress
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " the Internet address of the host"
+ ::= { ntpPeersVarEntry 5 }
+
+ntpPeersHostPort OBJECT-TYPE
+ SYNTAX Unsigned32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " 16-bit port number of the host"
+ ::= { ntpPeersVarEntry 6 }
+
+ntpPeersLeap OBJECT-TYPE
+ SYNTAX NTPLeapIndicator
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " two-bit code warning of an impending leap
+ second to be inserted in the NTP timescale."
+ ::= { ntpPeersVarEntry 7 }
+
+ntpPeersMode OBJECT-TYPE
+ SYNTAX INTEGER {
+ unspecified(0),
+ symmetricActive(1),
+ symmetricPassive(2),
+ client(3),
+ server(4),
+ broadcast(5),
+ reservedControl(6),
+ reservedPrivate(7)
+ }
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " the association mode,with values coded as
+ follows:
+ 0, unspecified
+ 1, symmetric active
+ 2, symmetric passive
+ 3, client
+ 4, server
+ 5, broadcast
+ 6, reserved for NTP control messages
+ 7, reserved for private use
+ "
+ ::= { ntpPeersVarEntry 8 }
+
+ntpPeersStratum OBJECT-TYPE
+ SYNTAX Integer32 (0..255)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " indicating the stratum of the peer clock.
+ 0, unspecified
+ 1, primary reference (e.g.,, calibrated atomic clock,
+ radio clock)
+ 2-255, secondary reference (via NTP)"
+ ::= { ntpPeersVarEntry 9 }
+
+ntpPeersPeerPoll OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "poll interval of the peer"
+ ::= { ntpPeersVarEntry 10 }
+
+ntpPeersHostPoll OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "poll interval of the host"
+ ::= { ntpPeersVarEntry 11 }
+
+ntpPeersPrecision OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "the same as the systemPrecision except this is
+ for the peer"
+ ::= { ntpPeersVarEntry 12 }
+
+ntpPeersRootDelay OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "the same as the systemRootDealy except this is for
+ the peer"
+ ::= { ntpPeersVarEntry 13 }
+
+ntpPeersRootDispersion OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "the same as the systemDispersion except this is for
+ the peer"
+ ::= { ntpPeersVarEntry 14 }
+
+ntpPeersRefId OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "the same as the systemRefid except this is for
+ the peer"
+ ::= { ntpPeersVarEntry 15 }
+
+ntpPeersRefTime OBJECT-TYPE
+ SYNTAX NTPTimeStamp
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "the same as the systemRefTime except this is for
+ the peer"
+ ::= { ntpPeersVarEntry 16 }
+
+ntpPeersOrgTime OBJECT-TYPE
+ SYNTAX NTPTimeStamp
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " the local time at the peer when its latest
+ NTP message was sent. If the peer becomes unreachable the
+ value is set to zero."
+ ::= { ntpPeersVarEntry 17 }
+
+ntpPeersReceiveTime OBJECT-TYPE
+ SYNTAX NTPTimeStamp
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "the local time when the latest NTP message
+ from the peer arrived. If the peer becomes unreachable the
+ value is set to zero."
+ ::= { ntpPeersVarEntry 18 }
+
+ntpPeersTransmitTime OBJECT-TYPE
+ SYNTAX NTPTimeStamp
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "the local time at which the NTP message
+ departed the sender."
+ ::= { ntpPeersVarEntry 19 }
+
+ntpPeersUpdateTime OBJECT-TYPE
+ SYNTAX NTPTimeStamp
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ " "
+ ::= { ntpPeersVarEntry 20 }
+
+ntpPeersReach OBJECT-TYPE
+ SYNTAX Unsigned32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "a shift register of NTP.WINDOW bits used to determine
+ the reachability status of the peer, with bits entering
+ from the least significant (rightmost) end. A peer is
+ considered reachable if at least one bit in this register is
+ set to one."
+ ::= { ntpPeersVarEntry 21 }
+
+ntpPeersTimer OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpPeersVarEntry 22 }
+
+ntpPeersOffset OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpPeersVarEntry 23 }
+
+ntpPeersDelay OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpPeersVarEntry 24 }
+
+ntpPeersDispersion OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpPeersVarEntry 25 }
+
+--
+-- Filter Group
+--
+-- Implementation of this group is optional. It must be implemented
+-- when the filter and selection algorithms described in Section 4
+-- of RFC 1305 are used.
+--
+
+--
+-- Filter Group Peer Variables Table
+--
+ntpFilterPeersVarTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF NtpFilterPeersVarEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "This table is an extension of the Peer Variables Table
+ in the Peer Group."
+ ::= { ntpFilter 1 }
+
+ntpFilterPeersVarEntry OBJECT-TYPE
+ SYNTAX NtpFilterPeersVarEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ AUGMENTS { ntpPeersVarEntry }
+ ::= { ntpFilterPeersVarTable 1 }
+
+NtpFilterPeersVarEntry ::= SEQUENCE {
+ ntpFilterValidEntries Integer32
+}
+
+ntpFilterValidEntries OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of valid entries for a peer in the Filter Register Table."
+ ::= { ntpFilterPeersVarEntry 1 }
+
+--
+-- Filter Register Table
+--
+
+ntpFilterRegisterTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF NtpFilterRegisterEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpFilter 2 }
+
+ntpFilterRegisterEntry OBJECT-TYPE
+ SYNTAX NtpFilterRegisterEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ INDEX { ntpPeersAssocId, ntpFilterIndex }
+ ::= { ntpFilterRegisterTable 1 }
+
+NtpFilterRegisterEntry ::= SEQUENCE {
+ ntpFilterIndex Unsigned32,
+ ntpFilterPeersOffset OCTET STRING,
+ ntpFilterPeersDelay OCTET STRING,
+ ntpFilterPeersDispersion OCTET STRING
+}
+
+ntpFilterIndex OBJECT-TYPE
+ SYNTAX Unsigned32
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpFilterRegisterEntry 1 }
+
+ntpFilterPeersOffset OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "the offset of the peer clock relative to the
+ local clock in seconds"
+ ::= { ntpFilterRegisterEntry 2 }
+
+ntpFilterPeersDelay OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "roundtrip delay of the peer clock relative to the
+ local clock over the network path between them, in seconds.
+ this variable can take on both positive and negative values,
+ depending on clock precision and skew-error accumulation."
+ ::= { ntpFilterRegisterEntry 3 }
+
+ntpFilterPeersDispersion OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "the maximum error of the peer clock relative to the
+ local clock over the network path between them, in seconds.
+ Only positive values greater than zero are possible."
+ ::= { ntpFilterRegisterEntry 4 }
+
+END
diff --git a/contrib/bsnmp/snmp_ntp/NTP-PROXY-MIB.txt b/contrib/bsnmp/snmp_ntp/NTP-PROXY-MIB.txt
new file mode 100644
index 000000000000..233dfec0bbcd
--- /dev/null
+++ b/contrib/bsnmp/snmp_ntp/NTP-PROXY-MIB.txt
@@ -0,0 +1,616 @@
+--
+-- NTP Proxy MIB, Revision 0.2, 7/25/97
+--
+
+NTP-PROXY-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+ NTPLeapIndicator, NTPTimeStamp
+ FROM NTP-MIB
+
+ Integer32, IpAddress, MODULE-IDENTITY, OBJECT-TYPE, Unsigned32,
+ enterprises
+ FROM SNMPv2-SMI
+
+ TEXTUAL-CONVENTION, TruthValue
+ FROM SNMPv2-TC;
+
+ntpProxyMIB MODULE-IDENTITY
+ LAST-UPDATED "199707251540Z"
+ ORGANIZATION
+ "University of Delaware"
+ CONTACT-INFO
+ "Adarsh Sethi
+ Department of Computer & Information Sciences
+ University of Delaware
+ Newark, DE 19716
+ Tel: +1 302 831 1945
+ E-mail: sethi@cis.udel.edu
+
+ David Mills
+ Department of Electrical Engineering
+ University of Delaware
+ Newark, DE 19716
+ Tel: +1 302 831 ????
+ E-mail: mills@ee.udel.edu"
+ DESCRIPTION
+ "This MIB module defines a MIB which provides mechanisms to
+ monitor and control many NTP servers via a Proxy Agent."
+ ::= { enterprises 1277 4 }
+
+--
+-- The position within the OID hierarchy of this MIB:
+--
+
+udel OBJECT IDENTIFIER
+ ::= { enterprises 1277 }
+
+--
+-- The various groups defined within this MIB definition:
+--
+
+ntpProxyControl OBJECT IDENTIFIER
+ ::= { ntpProxyMIB 1 }
+
+--
+-- Textual conventions:
+--
+
+NTPRowStatus ::= TEXTUAL-CONVENTION
+ STATUS current
+ DESCRIPTION
+ "The NTPRowStatus textual convention is modeled after the
+ RowStatus textual convention of RFC 1903, but is simpler
+ because it only allows one create operation (the create-
+ and-go of RowStatus) and does not allow row deletion. If
+ the state of the status column is `notInService' and the
+ management station tries to set it to `create', the
+ corresponding row is created and the operation is successful.
+ If the set to `create' is attempted when the status column
+ is in state `active', the operation fails and inconsistentValue
+ is returned. A management station is not permitted to delete
+ the conceptual row; deletion is carried out by the agent
+ in an autonomous manner."
+ SYNTAX INTEGER {
+ -- the following values are states:
+ -- these values may be read, but not written
+ active(1),
+ notInService(2),
+ -- the following value is an action:
+ -- this value may be written, but is never read
+ create(3)
+ }
+
+--
+-- Control group
+--
+
+--
+-- ProxyControl Table
+--
+
+ntpProxyControlTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF NtpProxyControlEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyControl 1 }
+
+ntpProxyControlEntry OBJECT-TYPE
+ SYNTAX NtpProxyControlEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ INDEX { ntpProxyServerIPAddr }
+ ::= { ntpProxyControlTable 1 }
+
+NtpProxyControlEntry ::= SEQUENCE {
+ ntpProxyServerIPAddr IpAddress,
+ ntpProxyControlStatus NTPRowStatus
+}
+
+ntpProxyServerIPAddr OBJECT-TYPE
+ SYNTAX IpAddress
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyControlEntry 1 }
+
+ntpProxyControlStatus OBJECT-TYPE
+ SYNTAX NTPRowStatus
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyControlEntry 2 }
+
+--
+-- Proxy Server System Table
+--
+
+ntpProxyServerSystemTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF NtpProxyServerSystemEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyControl 2 }
+
+ntpProxyServerSystemEntry OBJECT-TYPE
+ SYNTAX NtpProxyServerSystemEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ INDEX { ntpProxyServerIPAddr }
+ ::= { ntpProxyServerSystemTable 1 }
+
+NtpProxyServerSystemEntry ::= SEQUENCE {
+ ntpProxyServerSysLeap NTPLeapIndicator,
+ ntpProxyServerSysStratum Integer32,
+ ntpProxyServerSysPrecision Integer32,
+ ntpProxyServerSysRootDelay OCTET STRING,
+ ntpProxyServerSysRootDispersion OCTET STRING,
+ ntpProxyServerSysRefId OCTET STRING,
+ ntpProxyServerSysRefTime NTPTimeStamp,
+ ntpProxyServerSysPoll Integer32,
+ ntpProxyServerSysPeer Unsigned32,
+ ntpProxyServerSysPhase OCTET STRING,
+ ntpProxyServerSysFreq OCTET STRING,
+ ntpProxyServerSysError OCTET STRING,
+ ntpProxyServerSysClock NTPTimeStamp,
+ ntpProxyServerSysSystem OCTET STRING,
+ ntpProxyServerSysProcessor OCTET STRING
+}
+
+ntpProxyServerSysLeap OBJECT-TYPE
+ SYNTAX NTPLeapIndicator
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyServerSystemEntry 1 }
+
+ntpProxyServerSysStratum OBJECT-TYPE
+ SYNTAX Integer32 (0..255)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyServerSystemEntry 2 }
+
+ntpProxyServerSysPrecision OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyServerSystemEntry 3 }
+
+ntpProxyServerSysRootDelay OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyServerSystemEntry 4 }
+
+ntpProxyServerSysRootDispersion OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyServerSystemEntry 5 }
+
+ntpProxyServerSysRefId OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyServerSystemEntry 6 }
+
+ntpProxyServerSysRefTime OBJECT-TYPE
+ SYNTAX NTPTimeStamp
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyServerSystemEntry 7 }
+
+ntpProxyServerSysPoll OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyServerSystemEntry 8 }
+
+ntpProxyServerSysPeer OBJECT-TYPE
+ SYNTAX Unsigned32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyServerSystemEntry 9 }
+
+ntpProxyServerSysPhase OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyServerSystemEntry 10 }
+
+ntpProxyServerSysFreq OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyServerSystemEntry 11 }
+
+ntpProxyServerSysError OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyServerSystemEntry 12 }
+
+ntpProxyServerSysClock OBJECT-TYPE
+ SYNTAX NTPTimeStamp
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyServerSystemEntry 13 }
+
+ntpProxyServerSysSystem OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyServerSystemEntry 14 }
+
+ntpProxyServerSysProcessor OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyServerSystemEntry 15 }
+
+--
+-- Proxy Peer Variables Table
+--
+ntpProxyPeersVarTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF NtpProxyPeersVarEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyControl 3 }
+
+ntpProxyPeersVarEntry OBJECT-TYPE
+ SYNTAX NtpProxyPeersVarEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ INDEX { ntpProxyServerIPAddr, ntpProxyPeersAssocId }
+ ::= { ntpProxyPeersVarTable 1 }
+
+NtpProxyPeersVarEntry ::= SEQUENCE {
+ ntpProxyPeersAssocId Unsigned32,
+ ntpProxyPeersConfigured TruthValue,
+ ntpProxyPeersPeerAddress IpAddress,
+ ntpProxyPeersPeerPort Unsigned32,
+ ntpProxyPeersHostAddress IpAddress,
+ ntpProxyPeersHostPort Unsigned32,
+ ntpProxyPeersLeap NTPLeapIndicator,
+ ntpProxyPeersMode INTEGER,
+ ntpProxyPeersStratum Integer32,
+ ntpProxyPeersPeerPoll Integer32,
+ ntpProxyPeersHostPoll Integer32,
+ ntpProxyPeersPrecision Integer32,
+ ntpProxyPeersRootDelay OCTET STRING,
+ ntpProxyPeersRootDispersion OCTET STRING,
+ ntpProxyPeersRefId OCTET STRING,
+ ntpProxyPeersRefTime NTPTimeStamp,
+ ntpProxyPeersOrgTime NTPTimeStamp,
+ ntpProxyPeersReceiveTime NTPTimeStamp,
+ ntpProxyPeersTransmitTime NTPTimeStamp,
+ ntpProxyPeersUpdateTime NTPTimeStamp,
+ ntpProxyPeersReach Unsigned32,
+ ntpProxyPeersTimer Integer32,
+ ntpProxyPeersOffset OCTET STRING,
+ ntpProxyPeersDelay OCTET STRING,
+ ntpProxyPeersDispersion OCTET STRING,
+ ntpProxyPeersFilterValidEntries Integer32
+}
+
+ntpProxyPeersAssocId OBJECT-TYPE
+ SYNTAX Unsigned32
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 1 }
+
+ntpProxyPeersConfigured OBJECT-TYPE
+ SYNTAX TruthValue
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 2 }
+
+ntpProxyPeersPeerAddress OBJECT-TYPE
+ SYNTAX IpAddress
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 3 }
+
+ntpProxyPeersPeerPort OBJECT-TYPE
+ SYNTAX Unsigned32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 4 }
+
+ntpProxyPeersHostAddress OBJECT-TYPE
+ SYNTAX IpAddress
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 5 }
+
+ntpProxyPeersHostPort OBJECT-TYPE
+ SYNTAX Unsigned32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 6 }
+
+ntpProxyPeersLeap OBJECT-TYPE
+ SYNTAX NTPLeapIndicator
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 7 }
+
+ntpProxyPeersMode OBJECT-TYPE
+ SYNTAX INTEGER {
+ unspecified(0),
+ symmetricActive(1),
+ symmetricPassive(2),
+ client(3),
+ server(4),
+ broadcast(5),
+ reservedControl(6),
+ reservedPrivate(7) }
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 8 }
+
+ntpProxyPeersStratum OBJECT-TYPE
+ SYNTAX Integer32 (0..255)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 9 }
+
+ntpProxyPeersPeerPoll OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 10 }
+
+ntpProxyPeersHostPoll OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 11 }
+
+ntpProxyPeersPrecision OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 12 }
+
+ntpProxyPeersRootDelay OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 13 }
+
+ntpProxyPeersRootDispersion OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 14 }
+
+ntpProxyPeersRefId OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 15 }
+
+ntpProxyPeersRefTime OBJECT-TYPE
+ SYNTAX NTPTimeStamp
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 16 }
+
+ntpProxyPeersOrgTime OBJECT-TYPE
+ SYNTAX NTPTimeStamp
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 17 }
+
+ntpProxyPeersReceiveTime OBJECT-TYPE
+ SYNTAX NTPTimeStamp
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 18 }
+
+ntpProxyPeersTransmitTime OBJECT-TYPE
+ SYNTAX NTPTimeStamp
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 19 }
+
+ntpProxyPeersUpdateTime OBJECT-TYPE
+ SYNTAX NTPTimeStamp
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 20 }
+
+ntpProxyPeersReach OBJECT-TYPE
+ SYNTAX Unsigned32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 21 }
+
+ntpProxyPeersTimer OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 22 }
+
+ntpProxyPeersOffset OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 23 }
+
+ntpProxyPeersDelay OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 24 }
+
+ntpProxyPeersDispersion OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyPeersVarEntry 25 }
+
+ntpProxyPeersFilterValidEntries OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of valid entries for a peer in the Proxy Filter
+ Register Table. This number can be zero."
+ ::= { ntpProxyPeersVarEntry 26 }
+
+--
+-- Proxy Filter Register Table
+--
+
+ntpProxyFilterRegisterTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF NtpProxyFilterRegisterEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyControl 4 }
+
+ntpProxyFilterRegisterEntry OBJECT-TYPE
+ SYNTAX NtpProxyFilterRegisterEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ INDEX { ntpProxyServerIPAddr, ntpProxyPeersAssocId,
+ ntpProxyFilterIndex }
+ ::= { ntpProxyFilterRegisterTable 1 }
+
+NtpProxyFilterRegisterEntry ::= SEQUENCE {
+ ntpProxyFilterIndex Unsigned32,
+ ntpProxyFilterPeersOffset OCTET STRING,
+ ntpProxyFilterPeersDelay OCTET STRING,
+ ntpProxyFilterPeersDispersion OCTET STRING
+}
+
+ntpProxyFilterIndex OBJECT-TYPE
+ SYNTAX Unsigned32
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyFilterRegisterEntry 1 }
+
+ntpProxyFilterPeersOffset OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyFilterRegisterEntry 2 }
+
+ntpProxyFilterPeersDelay OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyFilterRegisterEntry 3 }
+
+ntpProxyFilterPeersDispersion OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { ntpProxyFilterRegisterEntry 4 }
+
+END
diff --git a/contrib/bsnmp/snmp_ntp/ntp_tree.def b/contrib/bsnmp/snmp_ntp/ntp_tree.def
new file mode 100644
index 000000000000..697bf80c6742
--- /dev/null
+++ b/contrib/bsnmp/snmp_ntp/ntp_tree.def
@@ -0,0 +1,122 @@
+#
+# Copyright (c) 2005
+# Hartmut Brandt.
+# All rights reserved.
+#
+# Author: Harti Brandt <harti@freebsd.org>
+#
+# Redistribution of this software and documentation and use in source and
+# binary forms, with or without modification, are permitted provided that
+# the following conditions are met:
+#
+# 1. Redistributions of source code or documentation must retain the above
+# copyright notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
+# AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+# FRAUNHOFER FOKUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# $Begemot: bsnmp/snmp_ntp/ntp_tree.def,v 1.2 2005/04/26 13:38:01 brandt_h Exp $
+#
+# Definition of the tree implemented by snmp_ntp.
+#
+(1 internet
+ (4 private
+ (1 enterprises
+ (1277 udel
+ (3 ntpMIB
+ (1 ntpSystem
+ (1 ntpSysLeap INTEGER op_ntpSystem GET)
+ (2 ntpSysStratum INTEGER op_ntpSystem GET)
+ (3 ntpSysPrecision INTEGER32 op_ntpSystem GET)
+ (4 ntpSysRootDelay OCTETSTRING op_ntpSystem GET)
+ (5 ntpSysRootDispersion OCTETSTRING op_ntpSystem GET)
+ (6 ntpSysRefId OCTETSTRING op_ntpSystem GET)
+ (7 ntpSysRefTime OCTETSTRING op_ntpSystem GET)
+ (8 ntpSysPoll INTEGER32 op_ntpSystem GET)
+ (9 ntpSysPeer UNSIGNED32 op_ntpSystem GET)
+# No idea what these should be
+# (10 ntpSysPhase OCTETSTRING op_ntpSystem GET)
+# (11 ntpSysFreq OCTETSTRING op_ntpSystem GET)
+# (12 ntpSysError OCTETSTRING op_ntpSystem GET)
+ (13 ntpSysClock OCTETSTRING op_ntpSystem GET)
+ (14 ntpSysSystem OCTETSTRING op_ntpSystem GET)
+ (15 ntpSysProcessor OCTETSTRING op_ntpSystem GET)
+ )
+ (2 ntpPeers
+ (1 ntpPeersVarTable
+ (1 ntpPeersVarEntry : UNSIGNED32 op_ntpPeersVarTable
+ (1 ntpPeersAssocId UNSIGNED32)
+ (2 ntpPeersConfigured INTEGER GET)
+ (3 ntpPeersPeerAddress IPADDRESS GET)
+ (4 ntpPeersPeerPort UNSIGNED32 GET)
+ (5 ntpPeersHostAddress IPADDRESS GET)
+ (6 ntpPeersHostPort UNSIGNED32 GET)
+ (7 ntpPeersLeap INTEGER GET)
+ (8 ntpPeersMode INTEGER GET)
+ (9 ntpPeersStratum INTEGER GET)
+ (10 ntpPeersPeerPoll INTEGER32 GET)
+ (11 ntpPeersHostPoll INTEGER32 GET)
+ (12 ntpPeersPrecision INTEGER32 GET)
+ (13 ntpPeersRootDelay OCTETSTRING GET)
+ (14 ntpPeersRootDispersion OCTETSTRING GET)
+ (15 ntpPeersRefId OCTETSTRING GET)
+ (16 ntpPeersRefTime OCTETSTRING GET)
+ (17 ntpPeersOrgTime OCTETSTRING GET)
+ (18 ntpPeersReceiveTime OCTETSTRING GET)
+ (19 ntpPeersTransmitTime OCTETSTRING GET)
+# No idea what these should be
+# (20 ntpPeersUpdateTime OCTETSTRING GET)
+ (21 ntpPeersReach UNSIGNED32 GET)
+ (22 ntpPeersTimer INTEGER32 GET)
+ (23 ntpPeersOffset OCTETSTRING GET)
+ (24 ntpPeersDelay OCTETSTRING GET)
+ (25 ntpPeersDispersion OCTETSTRING GET)
+ )
+ )
+ )
+ (3 ntpFilter
+ (1 ntpFilterPeersVarTable
+ (1 ntpFilterPeersVarEntry : UNSIGNED32 op_ntpFilterPeersVarTable
+ (1 ntpFilterValidEntries INTEGER32 GET)
+ )
+ )
+ (2 ntpFilterRegisterTable
+ (1 ntpFilterRegisterEntry : UNSIGNED32 UNSIGNED32 op_ntpFilterRegisterTable
+ (1 ntpFilterIndex UNSIGNED32)
+ (2 ntpFilterPeersOffset OCTETSTRING GET)
+ (3 ntpFilterPeersDelay OCTETSTRING GET)
+ (4 ntpFilterPeersDispersion OCTETSTRING GET)
+ )
+ )
+ )
+ )
+ )
+ (12325 fokus
+ (1 begemot
+ (201 begemotNtp
+ (1 begemotNtpObjects
+ (1 begemotNtpHost OCTETSTRING op_begemot_ntp GET)
+ (2 begemotNtpPort OCTETSTRING op_begemot_ntp GET)
+ (3 begemotNtpTimeout TIMETICKS op_begemot_ntp GET SET)
+ (4 begemotNtpDebug UNSIGNED32 op_begemot_ntp GET SET)
+ (5 begemotNtpJitter COUNTER64 op_begemot_ntp GET)
+ (6 begemotNtpStability COUNTER64 op_begemot_ntp GET)
+ )
+ )
+ )
+ )
+ )
+ )
+)
diff --git a/contrib/bsnmp/snmp_ntp/snmp_ntp.c b/contrib/bsnmp/snmp_ntp/snmp_ntp.c
new file mode 100644
index 000000000000..e8b7c0c9484d
--- /dev/null
+++ b/contrib/bsnmp/snmp_ntp/snmp_ntp.c
@@ -0,0 +1,1592 @@
+/*
+ * Copyright (c) 2005
+ * Hartmut Brandt.
+ * All rights reserved.
+ *
+ * Author: Harti Brandt <harti@freebsd.org>
+ *
+ * Redistribution of this software and documentation and use in source and
+ * binary forms, with or without modification, are permitted provided that
+ * the following conditions are met:
+ *
+ * 1. Redistributions of source code or documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
+ * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * FRAUNHOFER FOKUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Begemot: bsnmp/snmp_ntp/snmp_ntp.c,v 1.3 2005/04/26 16:26:23 brandt_h Exp $
+ *
+ * NTP interface for SNMPd.
+ */
+
+#include <sys/queue.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "snmpmod.h"
+#include "ntp_tree.h"
+#include "ntp_oid.h"
+
+#define NTPC_MAX 576
+#define NTPC_VERSION 3
+#define NTPC_MODE 6
+#define NTPC_DMAX 468
+
+#define NTPC_BIT_RESP 0x80
+#define NTPC_BIT_ERROR 0x40
+#define NTPC_BIT_MORE 0x20
+
+#define NTPC_OPMASK 0x1f
+#define NTPC_OP_READSTAT 1
+#define NTPC_OP_READVAR 2
+
+/* our module handle */
+static struct lmodule *module;
+
+/* debug flag */
+static uint32_t ntp_debug;
+#define DBG_DUMP_PKTS 0x01
+#define DBG_DUMP_VARS 0x02
+
+/* OIDs */
+static const struct asn_oid oid_ntpMIB = OIDX_ntpMIB;
+
+/* the Object Resource registration index */
+static u_int reg_index;
+
+/* last time we've fetch the system variables */
+static uint32_t sysinfo_tick;
+
+/* cached system variables */
+static int32_t sys_leap;
+static int sysb_leap;
+static int32_t sys_stratum;
+static int sysb_stratum;
+static int32_t sys_precision;
+static int sysb_precision;
+static char *sys_rootdelay;
+static char *sys_rootdispersion;
+static char *sys_refid;
+static char sys_reftime[8];
+static int sysb_reftime;
+static int32_t sys_poll;
+static int sysb_poll;
+static uint32_t sys_peer;
+static int sysb_peer;
+static u_char sys_clock[8];
+static int sysb_clock;
+static char *sys_system;
+static char *sys_processor;
+static int sysb_jitter;
+static double sys_jitter;
+static int sysb_stability;
+static double sys_stability;
+
+/* last time we've fetch the peer list */
+static uint32_t peers_tick;
+
+/* request sequence number generator */
+static uint16_t seqno;
+
+/* NTPD socket */
+static int ntpd_sock;
+static void *ntpd_fd;
+
+struct peer {
+ /* required entries for macros */
+ uint32_t index;
+ TAILQ_ENTRY(peer) link;
+
+ int32_t config; /* config bit */
+ u_char srcadr[4]; /* PeerAddress */
+ uint32_t srcport; /* PeerPort */
+ u_char dstadr[4]; /* HostAddress */
+ uint32_t dstport; /* HostPort */
+ int32_t leap; /* Leap */
+ int32_t hmode; /* Mode */
+ int32_t stratum; /* Stratum */
+ int32_t ppoll; /* PeerPoll */
+ int32_t hpoll; /* HostPoll */
+ int32_t precision; /* Precision */
+ char *rootdelay; /* RootDelay */
+ char *rootdispersion;/* RootDispersion */
+ char *refid; /* RefId */
+ u_char reftime[8]; /* RefTime */
+ u_char orgtime[8]; /* OrgTime */
+ u_char rcvtime[8]; /* ReceiveTime */
+ u_char xmttime[8]; /* TransmitTime */
+ u_int32_t reach; /* Reach */
+ int32_t timer; /* Timer */
+ char *offset; /* Offset */
+ char *delay; /* Delay */
+ char *dispersion; /* Dispersion */
+ int32_t filt_entries;
+};
+TAILQ_HEAD(peer_list, peer);
+
+/* list of peers */
+static struct peer_list peers = TAILQ_HEAD_INITIALIZER(peers);
+
+struct filt {
+ /* required fields */
+ struct asn_oid index;
+ TAILQ_ENTRY(filt) link;
+
+ char *offset;
+ char *delay;
+ char *dispersion;
+};
+TAILQ_HEAD(filt_list, filt);
+
+/* list of filters */
+static struct filt_list filts = TAILQ_HEAD_INITIALIZER(filts);
+
+/* configuration */
+static u_char *ntp_host;
+static u_char *ntp_port;
+static uint32_t ntp_timeout;
+
+static void ntpd_input(int, void *);
+static int open_socket(void);
+
+/* the initialisation function */
+static int
+ntp_init(struct lmodule *mod, int argc, char *argv[] __unused)
+{
+
+ module = mod;
+
+ if (argc != 0) {
+ syslog(LOG_ERR, "bad number of arguments for %s", __func__);
+ return (EINVAL);
+ }
+
+ ntp_host = strdup("localhost");
+ ntp_port = strdup("ntp");
+ ntp_timeout = 50; /* 0.5sec */
+
+ return (0);
+}
+
+/*
+ * Module is started
+ */
+static void
+ntp_start(void)
+{
+
+ if (open_socket() != -1) {
+ ntpd_fd = fd_select(ntpd_sock, ntpd_input, NULL, module);
+ if (ntpd_fd == NULL) {
+ syslog(LOG_ERR, "fd_select failed on ntpd socket: %m");
+ return;
+ }
+ }
+ reg_index = or_register(&oid_ntpMIB, "The MIB for NTP.", module);
+}
+
+/*
+ * Called, when the module is to be unloaded after it was successfully loaded
+ */
+static int
+ntp_fini(void)
+{
+
+ or_unregister(reg_index);
+ fd_deselect(ntpd_fd);
+
+ return (0);
+}
+
+const struct snmp_module config = {
+ .comment = "This module implements the NTP MIB",
+ .init = ntp_init,
+ .start = ntp_start,
+ .fini = ntp_fini,
+ .tree = ntp_ctree,
+ .tree_size = ntp_CTREE_SIZE,
+};
+
+/*
+ * Open the NTPD socket
+ */
+static int
+open_socket(void)
+{
+ struct addrinfo hints, *res, *res0;
+ int error;
+ const char *cause;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM;
+
+ error = getaddrinfo(ntp_host, ntp_port, &hints, &res0);
+ if (error) {
+ syslog(LOG_ERR, "%s(%s): %s", ntp_host, ntp_port,
+ gai_strerror(error));
+ return (-1);
+ }
+
+ ntpd_sock = -1;
+ cause = "no address";
+ errno = EADDRNOTAVAIL;
+ for (res = res0; res != NULL; res = res->ai_next) {
+ ntpd_sock = socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol);
+ if (ntpd_sock == -1) {
+ cause = "socket";
+ continue;
+ }
+ if (connect(ntpd_sock, res->ai_addr, res->ai_addrlen) == -1) {
+ cause = "connect";
+ (void)close(ntpd_sock);
+ ntpd_sock = -1;
+ continue;
+ }
+ break;
+ }
+ if (ntpd_sock == -1) {
+ syslog(LOG_ERR, "%s: %m", cause);
+ return (-1);
+ }
+ freeaddrinfo(res0);
+ return (0);
+}
+
+/*
+ * Dump a packet
+ */
+static void
+dump_packet(const u_char *pkt, size_t ret)
+{
+ char buf[8 * 3 + 1];
+ size_t i, j;
+
+ for (i = 0; i < ret; i += 8) {
+ buf[0] = '\0';
+ for (j = 0; i + j < (size_t)ret && j < 8; j++)
+ sprintf(buf + strlen(buf), " %02x", pkt[i + j]);
+ syslog(LOG_INFO, "%04zu:%s", i, buf);
+ }
+}
+
+/*
+ * Execute an NTP request.
+ */
+static int
+ntpd_request(u_int op, u_int associd, const char *vars)
+{
+ u_char *rpkt;
+ u_char *ptr;
+ size_t vlen;
+ ssize_t ret;
+
+ if ((rpkt = malloc(NTPC_MAX)) == NULL) {
+ syslog(LOG_ERR, "%m");
+ return (-1);
+ }
+ memset(rpkt, 0, NTPC_MAX);
+
+ ptr = rpkt;
+ *ptr++ = (NTPC_VERSION << 3) | NTPC_MODE;
+ *ptr++ = op;
+
+ if (++seqno == 0)
+ seqno++;
+ *ptr++ = seqno >> 8;
+ *ptr++ = seqno;
+
+ /* skip status */
+ ptr += 2;
+
+ *ptr++ = associd >> 8;
+ *ptr++ = associd;
+
+ /* skip offset */
+ ptr += 2;
+
+ if (vars != NULL) {
+ vlen = strlen(vars);
+ if (vlen > NTPC_DMAX) {
+ syslog(LOG_ERR, "NTP request too long (%zu)", vlen);
+ free(rpkt);
+ return (-1);
+ }
+ *ptr++ = vlen >> 8;
+ *ptr++ = vlen;
+
+ memcpy(ptr, vars, vlen);
+ ptr += vlen;
+ } else
+ /* skip data length (is already zero) */
+ ptr += 2;
+
+ while ((ptr - rpkt) % 4 != 0)
+ *ptr++ = 0;
+
+ if (ntp_debug & DBG_DUMP_PKTS) {
+ syslog(LOG_INFO, "sending %zd bytes", ptr - rpkt);
+ dump_packet(rpkt, ptr - rpkt);
+ }
+
+ ret = send(ntpd_sock, rpkt, ptr - rpkt, 0);
+ if (ret == -1) {
+ syslog(LOG_ERR, "cannot send to ntpd: %m");
+ free(rpkt);
+ return (-1);
+ }
+}
+
+/*
+ * Callback if packet arrived from NTPD
+ */
+static int
+ntpd_read(uint16_t *op, uint16_t *associd, u_char **data, size_t *datalen)
+{
+ u_char pkt[NTPC_MAX + 1];
+ u_char *ptr, *nptr;
+ u_int n;
+ ssize_t ret;
+ size_t z;
+ u_int offset; /* current offset */
+ int more; /* more flag */
+ int sel;
+ struct timeval inc, end, rem;
+ fd_set iset;
+
+ *datalen = 0;
+ *data = NULL;
+ offset = 0;
+
+ inc.tv_sec = ntp_timeout / 100;
+ inc.tv_usec = (ntp_timeout % 100) * 1000;
+
+ (void)gettimeofday(&end, NULL);
+ timeradd(&end, &inc, &end);
+
+ next:
+ /* compute remaining time */
+ (void)gettimeofday(&rem, NULL);
+ if (timercmp(&rem, &end, >=)) {
+ /* do a poll */
+ rem.tv_sec = 0;
+ rem.tv_usec = 0;
+ } else {
+ timersub(&end, &rem, &rem);
+ }
+
+ /* select */
+ FD_ZERO(&iset);
+ FD_SET(ntpd_sock, &iset);
+ sel = select(ntpd_sock + 1, &iset, NULL, NULL, &rem);
+ if (sel == -1) {
+ if (errno == EINTR)
+ goto next;
+ syslog(LOG_ERR, "select ntpd_sock: %m");
+ free(*data);
+ return (-1);
+ }
+ if (sel == 0) {
+ syslog(LOG_ERR, "timeout on NTP connection");
+ free(*data);
+ return (-1);
+ }
+
+ /* now read it */
+ ret = recv(ntpd_sock, pkt, sizeof(pkt), 0);
+ if (ret == -1) {
+ syslog(LOG_ERR, "error reading from ntpd: %m");
+ free(*data);
+ return (-1);
+ }
+
+ if (ntp_debug & DBG_DUMP_PKTS) {
+ syslog(LOG_INFO, "got %zd bytes", ret);
+ dump_packet(pkt, (size_t)ret);
+ }
+
+ ptr = pkt;
+ if (*ptr != ((NTPC_VERSION << 3) | NTPC_MODE)) {
+ syslog(LOG_ERR, "unexpected packet version 0x%x", *ptr);
+ free(*data);
+ return (-1);
+ }
+ ptr++;
+
+ if (!(*ptr & NTPC_BIT_RESP)) {
+ syslog(LOG_ERR, "not a response packet");
+ return (-1);
+ }
+ if (*ptr & NTPC_BIT_ERROR) {
+ z = *datalen - 12;
+ if (z > NTPC_DMAX)
+ z = NTPC_DMAX;
+ syslog(LOG_ERR, "error response: %.*s", (int)z, pkt + 12);
+ free(*data);
+ return (-1);
+ }
+ more = (*ptr & NTPC_BIT_MORE);
+
+ *op = *ptr++ & NTPC_OPMASK;
+
+ /* seqno */
+ n = *ptr++ << 8;
+ n |= *ptr++;
+
+ if (n != seqno) {
+ syslog(LOG_ERR, "expecting seqno %u, got %u", seqno, n);
+ free(*data);
+ return (-1);
+ }
+
+ /* status */
+ n = *ptr++ << 8;
+ n |= *ptr++;
+
+ /* associd */
+ *associd = *ptr++ << 8;
+ *associd |= *ptr++;
+
+ /* offset */
+ n = *ptr++ << 8;
+ n |= *ptr++;
+
+ if (n != offset) {
+ syslog(LOG_ERR, "offset: expecting %u, got %u", offset, n);
+ free(*data);
+ return (-1);
+ }
+
+ /* count */
+ n = *ptr++ << 8;
+ n |= *ptr++;
+
+ if ((size_t)ret < 12 + n) {
+ syslog(LOG_ERR, "packet too short");
+ return (-1);
+ }
+
+ nptr = realloc(*data, *datalen + n);
+ if (nptr == NULL) {
+ syslog(LOG_ERR, "cannot allocate memory: %m");
+ free(*data);
+ return (-1);
+ }
+ *data = nptr;
+
+ memcpy(*data + offset, ptr, n);
+ *datalen += n;
+
+ if (!more)
+ return (0);
+
+ offset += n;
+ goto next;
+}
+
+/*
+ * Send a request and wait for the response
+ */
+static int
+ntpd_dialog(u_int op, u_int associd, const char *vars, u_char **data,
+ size_t *datalen)
+{
+ uint16_t rassocid;
+ uint16_t rop;
+
+ if (ntpd_request(op, associd, vars) == -1)
+ return (-1);
+ if (ntpd_read(&rop, &rassocid, data, datalen) == -1)
+ return (-1);
+
+ if (rop != op) {
+ syslog(LOG_ERR, "bad response op 0x%x", rop);
+ free(data);
+ return (-1);
+ }
+
+ if (associd != rassocid) {
+ syslog(LOG_ERR, "response for wrong associd");
+ free(data);
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Callback if packet arrived from NTPD
+ */
+static void
+ntpd_input(int fd __unused, void *arg __unused)
+{
+ uint16_t associd;
+ uint16_t op;
+ u_char *data;
+ size_t datalen;
+
+ if (ntpd_read(&op, &associd, &data, &datalen) == -1)
+ return;
+
+ free(data);
+}
+
+/*
+ * Find the value of a variable
+ */
+static int
+ntpd_parse(u_char **data, size_t *datalen, char **namep, char **valp)
+{
+ u_char *ptr = *data;
+ u_char *end = ptr + *datalen;
+ char *ptr1;
+ char endc;
+
+ /* skip leading spaces */
+ while (ptr < end && isspace((int)*ptr))
+ ptr++;
+
+ if (ptr == end)
+ return (0);
+
+ *namep = ptr;
+
+ /* skip to space or '=' or ','*/
+ while (ptr < end && !isspace((int)*ptr) && *ptr != '=' && *ptr != ',')
+ ptr++;
+ endc = *ptr;
+ *ptr++ = '\0';
+
+ /* skip space */
+ while (ptr < end && isspace((int)*ptr))
+ ptr++;
+
+ if (ptr == end || endc == ',') {
+ /* no value */
+ *valp = NULL;
+ *datalen -= ptr - *data;
+ *data = ptr;
+ return (1);
+ }
+
+ if (*ptr == '"') {
+ /* quoted */
+ ptr++;
+ *valp = ptr;
+ while (ptr < end && *ptr != '"')
+ ptr++;
+ if (ptr == end)
+ return (0);
+
+ *ptr++ = '\0';
+
+ /* find comma */
+ while (ptr < end && isspace((int)*ptr) && *ptr == ',')
+ ptr++;
+ } else {
+ *valp = ptr;
+
+ /* skip to end of value */
+ while (ptr < end && *ptr != ',')
+ ptr++;
+
+ /* remove trailing blanks */
+ for (ptr1 = ptr; ptr1 > *valp; ptr1--)
+ if (!isspace((int)ptr1[-1]))
+ break;
+ *ptr1 = '\0';
+
+ if (ptr < end)
+ ptr++;
+ }
+
+ *datalen -= ptr - *data;
+ *data = ptr;
+
+ return (1);
+}
+
+/*
+ * Parse an int32 value
+ */
+static int
+val_parse_int32(const char *val, int32_t *p, int32_t min, int32_t max, int base)
+{
+ long n;
+ char *end;
+
+ errno = 0;
+ n = strtol(val, &end, base);
+ if (errno != 0 || *end != '\0')
+ return (0);
+ if (n < min || n > max)
+ return (0);
+ *p = (int32_t)n;
+ return (1);
+}
+
+/*
+ * Parse an uint32 value
+ */
+static int
+val_parse_uint32(const char *val, uint32_t *p, uint32_t min, uint32_t max,
+ int base)
+{
+ u_long n;
+ char *end;
+
+ errno = 0;
+ n = strtoul(val, &end, base);
+ if (errno != 0 || *end != '\0')
+ return (0);
+ if (n < min || n > max)
+ return (0);
+ *p = (uint32_t)n;
+ return (1);
+}
+
+/*
+ * Parse a double
+ */
+static int
+val_parse_double(const char *val, double *p)
+{
+ char *end;
+
+ errno = 0;
+ *p = strtod(val, &end);
+ if (errno != 0 || *end != '\0')
+ return (0);
+ return (1);
+}
+
+static int
+val_parse_ts(const char *val, char *buf)
+{
+ int r, n;
+ u_int i, f;
+
+ if (strlen(val) > 2 && val[0] == '0' && val[1] == 'x') {
+ /* hex format */
+ r = sscanf(val + 2, "%x.%x%n", &i, &f, &n);
+ if (r != 2 || (size_t)n != strlen(val + 2))
+ return (0);
+ } else {
+ /* probably decimal */
+ r = sscanf(val, "%d.%d%n", &i, &f, &n);
+ if (r != 2 || (size_t)n != strlen(val))
+ return (0);
+ }
+ buf[0] = i >> 24;
+ buf[1] = i >> 16;
+ buf[2] = i >> 8;
+ buf[3] = i >> 0;
+ buf[4] = f >> 24;
+ buf[5] = f >> 16;
+ buf[6] = f >> 8;
+ buf[7] = f >> 0;
+ return (1);
+}
+
+/*
+ * Parse an IP address. This resolves non-numeric names.
+ */
+static int
+val_parse_ip(const char *val, u_char ip[4])
+{
+ int r, n, error;
+ struct addrinfo hints, *res0;
+ struct sockaddr_in *sin;
+
+ r = sscanf(val, "%hhd.%hhd.%hhd.%hhd%n",
+ &ip[0], &ip[1], &ip[2], &ip[3], &n);
+ if (n == 4 && (size_t)n == strlen(val))
+ return (0);
+
+ memset(ip, 0, 4);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM;
+
+ error = getaddrinfo(val, NULL, &hints, &res0);
+ if (error) {
+ syslog(LOG_ERR, "%s: %s", val, gai_strerror(error));
+ return (-1);
+ }
+ if (res0 == NULL) {
+ syslog(LOG_ERR, "%s: no address", val);
+ return (-1);
+ }
+
+ sin = (struct sockaddr_in *)(void *)res0->ai_addr;
+ ip[3] = sin->sin_addr.s_addr >> 24;
+ ip[2] = sin->sin_addr.s_addr >> 16;
+ ip[1] = sin->sin_addr.s_addr >> 8;
+ ip[0] = sin->sin_addr.s_addr >> 0;
+
+ freeaddrinfo(res0);
+ return (0);
+}
+
+/*
+ * Fetch system info
+ */
+static int
+fetch_sysinfo(void)
+{
+ u_char *data;
+ u_char *ptr;
+ size_t datalen;
+ char *name;
+ char *val;
+
+ if (ntpd_dialog(NTPC_OP_READVAR, 0,
+ "leap,stratum,precision,rootdelay,rootdispersion,refid,reftime,"
+ "poll,peer,clock,system,processor,jitter,stability",
+ &data, &datalen))
+ return (-1);
+
+ /* clear info */
+ sysb_leap = 0;
+ sysb_stratum = 0;
+ sysb_precision = 0;
+ free(sys_rootdelay);
+ sys_rootdelay = NULL;
+ free(sys_rootdispersion);
+ sys_rootdispersion = NULL;
+ free(sys_refid);
+ sys_refid = NULL;
+ sysb_reftime = 0;
+ sysb_poll = 0;
+ sysb_peer = 0;
+ sysb_clock = 0;
+ free(sys_system);
+ sys_system = NULL;
+ free(sys_processor);
+ sys_processor = NULL;
+ sysb_jitter = 0;
+ sysb_stability = 0;
+
+ ptr = data;
+ while (ntpd_parse(&ptr, &datalen, &name, &val)) {
+ if (ntp_debug & DBG_DUMP_VARS)
+ syslog(LOG_DEBUG, "%s: '%s'='%s'", __func__, name, val);
+ if (strcmp(name, "leap") == 0 ||
+ strcmp(name, "sys.leap") == 0) {
+ sysb_leap = val_parse_int32(val, &sys_leap,
+ 0, 3, 2);
+
+ } else if (strcmp(name, "stratum") == 0 ||
+ strcmp(name, "sys.stratum") == 0) {
+ sysb_stratum = val_parse_int32(val, &sys_stratum,
+ 0, 255, 0);
+
+ } else if (strcmp(name, "precision") == 0 ||
+ strcmp(name, "sys.precision") == 0) {
+ sysb_precision = val_parse_int32(val, &sys_precision,
+ INT32_MIN, INT32_MAX, 0);
+
+ } else if (strcmp(name, "rootdelay") == 0 ||
+ strcmp(name, "sys.rootdelay") == 0) {
+ sys_rootdelay = strdup(val);
+
+ } else if (strcmp(name, "rootdispersion") == 0 ||
+ strcmp(name, "sys.rootdispersion") == 0) {
+ sys_rootdispersion = strdup(val);
+
+ } else if (strcmp(name, "refid") == 0 ||
+ strcmp(name, "sys.refid") == 0) {
+ sys_refid = strdup(val);
+
+ } else if (strcmp(name, "reftime") == 0 ||
+ strcmp(name, "sys.reftime") == 0) {
+ sysb_reftime = val_parse_ts(val, sys_reftime);
+
+ } else if (strcmp(name, "poll") == 0 ||
+ strcmp(name, "sys.poll") == 0) {
+ sysb_poll = val_parse_int32(val, &sys_poll,
+ INT32_MIN, INT32_MAX, 0);
+
+ } else if (strcmp(name, "peer") == 0 ||
+ strcmp(name, "sys.peer") == 0) {
+ sysb_peer = val_parse_uint32(val, &sys_peer,
+ 0, UINT32_MAX, 0);
+
+ } else if (strcmp(name, "clock") == 0 ||
+ strcmp(name, "sys.clock") == 0) {
+ sysb_clock = val_parse_ts(val, sys_clock);
+
+ } else if (strcmp(name, "system") == 0 ||
+ strcmp(name, "sys.system") == 0) {
+ sys_system = strdup(val);
+
+ } else if (strcmp(name, "processor") == 0 ||
+ strcmp(name, "sys.processor") == 0) {
+ sys_processor = strdup(val);
+
+ } else if (strcmp(name, "jitter") == 0 ||
+ strcmp(name, "sys.jitter") == 0) {
+ sysb_jitter = val_parse_double(val, &sys_jitter);
+
+ } else if (strcmp(name, "stability") == 0 ||
+ strcmp(name, "sys.stability") == 0) {
+ sysb_stability = val_parse_double(val, &sys_stability);
+ }
+ }
+
+ free(data);
+ return (0);
+}
+
+static int
+parse_filt(char *val, uint16_t associd, int which)
+{
+ char *w;
+ int cnt;
+ struct filt *f;
+
+ cnt = 0;
+ for (w = strtok(val, " \t"); w != NULL; w = strtok(NULL, " \t")) {
+ TAILQ_FOREACH(f, &filts, link)
+ if (f->index.subs[0] == associd &&
+ f->index.subs[1] == (asn_subid_t)(cnt + 1))
+ break;
+ if (f == NULL) {
+ f = malloc(sizeof(*f));
+ memset(f, 0, sizeof(*f));
+ f->index.len = 2;
+ f->index.subs[0] = associd;
+ f->index.subs[1] = cnt + 1;
+
+ INSERT_OBJECT_OID(f, &filts);
+ }
+
+ switch (which) {
+
+ case 0:
+ f->offset = strdup(w);
+ break;
+
+ case 1:
+ f->delay = strdup(w);
+ break;
+
+ case 2:
+ f->dispersion = strdup(w);
+ break;
+
+ default:
+ abort();
+ }
+ cnt++;
+ }
+ return (cnt);
+}
+
+/*
+ * Fetch the complete peer list
+ */
+static int
+fetch_peers(void)
+{
+ u_char *data, *pdata, *ptr;
+ size_t datalen, pdatalen;
+ int i;
+ struct peer *p;
+ struct filt *f;
+ uint16_t associd;
+ char *name, *val;
+
+ /* free the old list */
+ while ((p = TAILQ_FIRST(&peers)) != NULL) {
+ TAILQ_REMOVE(&peers, p, link);
+ free(p->rootdelay);
+ free(p->rootdispersion);
+ free(p->refid);
+ free(p->offset);
+ free(p->delay);
+ free(p->dispersion);
+ free(p);
+ }
+ while ((f = TAILQ_FIRST(&filts)) != NULL) {
+ TAILQ_REMOVE(&filts, f, link);
+ free(f->offset);
+ free(f->delay);
+ free(f->dispersion);
+ free(f);
+ }
+
+ /* fetch the list of associations */
+ if (ntpd_dialog(NTPC_OP_READSTAT, 0, NULL, &data, &datalen))
+ return (-1);
+
+ for (i = 0; i < (int)(datalen / 4); i++) {
+ associd = data[4 * i + 0] << 8;
+ associd |= data[4 * i + 1] << 0;
+
+ /* ask for the association variables */
+ if (ntpd_dialog(NTPC_OP_READVAR, associd,
+ "config,srcadr,srcport,dstadr,dstport,leap,hmode,stratum,"
+ "hpoll,ppoll,precision,rootdelay,rootdispersion,refid,"
+ "reftime,org,rec,xmt,reach,timer,offset,delay,dispersion,"
+ "filtdelay,filtoffset,filtdisp",
+ &pdata, &pdatalen)) {
+ free(data);
+ return (-1);
+ }
+
+ /* now save and parse the data */
+ p = malloc(sizeof(*p));
+ if (p == NULL) {
+ free(data);
+ syslog(LOG_ERR, "%m");
+ return (-1);
+ }
+ memset(p, 0, sizeof(*p));
+ p->index = associd;
+ INSERT_OBJECT_INT(p, &peers);
+
+ ptr = pdata;
+ while (ntpd_parse(&ptr, &pdatalen, &name, &val)) {
+ if (ntp_debug & DBG_DUMP_VARS)
+ syslog(LOG_DEBUG, "%s: '%s'='%s'",
+ __func__, name, val);
+ if (strcmp(name, "config") == 0 ||
+ strcmp(name, "peer.config") == 0) {
+ val_parse_int32(val, &p->config, 0, 1, 0);
+
+ } else if (strcmp(name, "srcadr") == 0 ||
+ strcmp(name, "peer.srcadr") == 0) {
+ val_parse_ip(val, p->srcadr);
+
+ } else if (strcmp(name, "srcport") == 0 ||
+ strcmp(name, "peer.srcport") == 0) {
+ val_parse_uint32(val, &p->srcport,
+ 1, 65535, 0);
+
+ } else if (strcmp(name, "dstadr") == 0 ||
+ strcmp(name, "peer.dstadr") == 0) {
+ val_parse_ip(val, p->dstadr);
+
+ } else if (strcmp(name, "dstport") == 0 ||
+ strcmp(name, "peer.dstport") == 0) {
+ val_parse_uint32(val, &p->dstport,
+ 1, 65535, 0);
+
+ } else if (strcmp(name, "leap") == 0 ||
+ strcmp(name, "peer.leap") == 0) {
+ val_parse_int32(val, &p->leap, 0, 3, 2);
+
+ } else if (strcmp(name, "hmode") == 0 ||
+ strcmp(name, "peer.hmode") == 0) {
+ val_parse_int32(val, &p->hmode, 0, 7, 0);
+
+ } else if (strcmp(name, "stratum") == 0 ||
+ strcmp(name, "peer.stratum") == 0) {
+ val_parse_int32(val, &p->stratum, 0, 255, 0);
+
+ } else if (strcmp(name, "ppoll") == 0 ||
+ strcmp(name, "peer.ppoll") == 0) {
+ val_parse_int32(val, &p->ppoll,
+ INT32_MIN, INT32_MAX, 0);
+
+ } else if (strcmp(name, "hpoll") == 0 ||
+ strcmp(name, "peer.hpoll") == 0) {
+ val_parse_int32(val, &p->hpoll,
+ INT32_MIN, INT32_MAX, 0);
+
+ } else if (strcmp(name, "precision") == 0 ||
+ strcmp(name, "peer.precision") == 0) {
+ val_parse_int32(val, &p->hpoll,
+ INT32_MIN, INT32_MAX, 0);
+
+ } else if (strcmp(name, "rootdelay") == 0 ||
+ strcmp(name, "peer.rootdelay") == 0) {
+ p->rootdelay = strdup(val);
+
+ } else if (strcmp(name, "rootdispersion") == 0 ||
+ strcmp(name, "peer.rootdispersion") == 0) {
+ p->rootdispersion = strdup(val);
+
+ } else if (strcmp(name, "refid") == 0 ||
+ strcmp(name, "peer.refid") == 0) {
+ p->refid = strdup(val);
+
+ } else if (strcmp(name, "reftime") == 0 ||
+ strcmp(name, "sys.reftime") == 0) {
+ val_parse_ts(val, p->reftime);
+
+ } else if (strcmp(name, "org") == 0 ||
+ strcmp(name, "sys.org") == 0) {
+ val_parse_ts(val, p->orgtime);
+
+ } else if (strcmp(name, "rec") == 0 ||
+ strcmp(name, "sys.rec") == 0) {
+ val_parse_ts(val, p->rcvtime);
+
+ } else if (strcmp(name, "xmt") == 0 ||
+ strcmp(name, "sys.xmt") == 0) {
+ val_parse_ts(val, p->xmttime);
+
+ } else if (strcmp(name, "reach") == 0 ||
+ strcmp(name, "peer.reach") == 0) {
+ val_parse_uint32(val, &p->reach,
+ 0, 65535, 0);
+
+ } else if (strcmp(name, "timer") == 0 ||
+ strcmp(name, "peer.timer") == 0) {
+ val_parse_int32(val, &p->timer,
+ INT32_MIN, INT32_MAX, 0);
+
+ } else if (strcmp(name, "offset") == 0 ||
+ strcmp(name, "peer.offset") == 0) {
+ p->offset = strdup(val);
+
+ } else if (strcmp(name, "delay") == 0 ||
+ strcmp(name, "peer.delay") == 0) {
+ p->delay = strdup(val);
+
+ } else if (strcmp(name, "dispersion") == 0 ||
+ strcmp(name, "peer.dispersion") == 0) {
+ p->dispersion = strdup(val);
+
+ } else if (strcmp(name, "filtdelay") == 0 ||
+ strcmp(name, "peer.filtdelay") == 0) {
+ p->filt_entries = parse_filt(val, associd, 0);
+
+ } else if (strcmp(name, "filtoffset") == 0 ||
+ strcmp(name, "peer.filtoffset") == 0) {
+ p->filt_entries = parse_filt(val, associd, 1);
+
+ } else if (strcmp(name, "filtdisp") == 0 ||
+ strcmp(name, "peer.filtdisp") == 0) {
+ p->filt_entries = parse_filt(val, associd, 2);
+ }
+ }
+ free(pdata);
+ }
+
+ free(data);
+ return (0);
+}
+
+/*
+ * System variables - read-only scalars only.
+ */
+int
+op_ntpSystem(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];
+
+ switch (op) {
+
+ case SNMP_OP_GETNEXT:
+ abort();
+
+ case SNMP_OP_GET:
+ if (this_tick > sysinfo_tick) {
+ if (fetch_sysinfo() == -1)
+ return (SNMP_ERR_GENERR);
+ sysinfo_tick = this_tick;
+ }
+
+ switch (which) {
+
+ case LEAF_ntpSysLeap:
+ if (!sysb_leap)
+ return (SNMP_ERR_NOSUCHNAME);
+ value->v.integer = sys_leap;
+ break;
+
+ case LEAF_ntpSysStratum:
+ if (!sysb_stratum)
+ return (SNMP_ERR_NOSUCHNAME);
+ value->v.integer = sys_stratum;
+ break;
+
+ case LEAF_ntpSysPrecision:
+ if (!sysb_precision)
+ return (SNMP_ERR_NOSUCHNAME);
+ value->v.integer = sys_precision;
+ break;
+
+ case LEAF_ntpSysRootDelay:
+ if (sys_rootdelay == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ return (string_get(value, sys_rootdelay, -1));
+
+ case LEAF_ntpSysRootDispersion:
+ if (sys_rootdispersion == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ return (string_get(value, sys_rootdispersion, -1));
+
+ case LEAF_ntpSysRefId:
+ if (sys_refid == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ return (string_get(value, sys_refid, -1));
+
+ case LEAF_ntpSysRefTime:
+ if (sysb_reftime == 0)
+ return (SNMP_ERR_NOSUCHNAME);
+ return (string_get(value, sys_reftime, 8));
+
+ case LEAF_ntpSysPoll:
+ if (sysb_poll == 0)
+ return (SNMP_ERR_NOSUCHNAME);
+ value->v.integer = sys_poll;
+ break;
+
+ case LEAF_ntpSysPeer:
+ if (sysb_peer == 0)
+ return (SNMP_ERR_NOSUCHNAME);
+ value->v.uint32 = sys_peer;
+ break;
+
+ case LEAF_ntpSysClock:
+ if (sysb_clock == 0)
+ return (SNMP_ERR_NOSUCHNAME);
+ return (string_get(value, sys_clock, 8));
+
+ case LEAF_ntpSysSystem:
+ if (sys_system == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ return (string_get(value, sys_system, -1));
+
+ case LEAF_ntpSysProcessor:
+ if (sys_processor == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ return (string_get(value, sys_processor, -1));
+
+ default:
+ abort();
+ }
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_OP_SET:
+ return (SNMP_ERR_NOT_WRITEABLE);
+
+ case SNMP_OP_COMMIT:
+ case SNMP_OP_ROLLBACK:
+ abort();
+ }
+ abort();
+}
+
+int
+op_ntpPeersVarTable(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];
+ uint32_t peer;
+ struct peer *t;
+
+ if (this_tick > peers_tick) {
+ if (fetch_peers() == -1)
+ return (SNMP_ERR_GENERR);
+ peers_tick = this_tick;
+ }
+
+ switch (op) {
+
+ case SNMP_OP_GETNEXT:
+ t = NEXT_OBJECT_INT(&peers, &value->var, sub);
+ if (t == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ value->var.len = sub + 1;
+ value->var.subs[sub] = t->index;
+ break;
+
+ case SNMP_OP_GET:
+ t = FIND_OBJECT_INT(&peers, &value->var, sub);
+ if (t == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ break;
+
+ case SNMP_OP_SET:
+ if (index_decode(&value->var, sub, iidx, &peer))
+ return (SNMP_ERR_NO_CREATION);
+ t = FIND_OBJECT_INT(&peers, &value->var, sub);
+ if (t != NULL)
+ return (SNMP_ERR_NOT_WRITEABLE);
+ return (SNMP_ERR_NO_CREATION);
+
+ case SNMP_OP_COMMIT:
+ case SNMP_OP_ROLLBACK:
+ default:
+ abort();
+ }
+
+ /*
+ * Come here for GET and COMMIT
+ */
+ switch (which) {
+
+ case LEAF_ntpPeersConfigured:
+ value->v.integer = t->config;
+ break;
+
+ case LEAF_ntpPeersPeerAddress:
+ return (ip_get(value, t->srcadr));
+
+ case LEAF_ntpPeersPeerPort:
+ value->v.uint32 = t->srcport;
+ break;
+
+ case LEAF_ntpPeersHostAddress:
+ return (ip_get(value, t->dstadr));
+
+ case LEAF_ntpPeersHostPort:
+ value->v.uint32 = t->dstport;
+ break;
+
+ case LEAF_ntpPeersLeap:
+ value->v.integer = t->leap;
+ break;
+
+ case LEAF_ntpPeersMode:
+ value->v.integer = t->hmode;
+ break;
+
+ case LEAF_ntpPeersStratum:
+ value->v.integer = t->stratum;
+ break;
+
+ case LEAF_ntpPeersPeerPoll:
+ value->v.integer = t->ppoll;
+ break;
+
+ case LEAF_ntpPeersHostPoll:
+ value->v.integer = t->hpoll;
+ break;
+
+ case LEAF_ntpPeersPrecision:
+ value->v.integer = t->precision;
+ break;
+
+ case LEAF_ntpPeersRootDelay:
+ return (string_get(value, t->rootdelay, -1));
+
+ case LEAF_ntpPeersRootDispersion:
+ return (string_get(value, t->rootdispersion, -1));
+
+ case LEAF_ntpPeersRefId:
+ return (string_get(value, t->refid, -1));
+
+ case LEAF_ntpPeersRefTime:
+ return (string_get(value, t->reftime, 8));
+
+ case LEAF_ntpPeersOrgTime:
+ return (string_get(value, t->orgtime, 8));
+
+ case LEAF_ntpPeersReceiveTime:
+ return (string_get(value, t->rcvtime, 8));
+
+ case LEAF_ntpPeersTransmitTime:
+ return (string_get(value, t->xmttime, 8));
+
+ case LEAF_ntpPeersReach:
+ value->v.uint32 = t->reach;
+ break;
+
+ case LEAF_ntpPeersTimer:
+ value->v.uint32 = t->timer;
+ break;
+
+ case LEAF_ntpPeersOffset:
+ return (string_get(value, t->offset, -1));
+
+ case LEAF_ntpPeersDelay:
+ return (string_get(value, t->delay, -1));
+
+ case LEAF_ntpPeersDispersion:
+ return (string_get(value, t->dispersion, -1));
+
+ default:
+ abort();
+ }
+ return (SNMP_ERR_NOERROR);
+}
+
+
+int
+op_ntpFilterPeersVarTable(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];
+ uint32_t peer;
+ struct peer *t;
+
+ if (this_tick > peers_tick) {
+ if (fetch_peers() == -1)
+ return (SNMP_ERR_GENERR);
+ peers_tick = this_tick;
+ }
+
+ switch (op) {
+
+ case SNMP_OP_GETNEXT:
+ t = NEXT_OBJECT_INT(&peers, &value->var, sub);
+ if (t == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ value->var.len = sub + 1;
+ value->var.subs[sub] = t->index;
+ break;
+
+ case SNMP_OP_GET:
+ t = FIND_OBJECT_INT(&peers, &value->var, sub);
+ if (t == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ break;
+
+ case SNMP_OP_SET:
+ if (index_decode(&value->var, sub, iidx, &peer))
+ return (SNMP_ERR_NO_CREATION);
+ t = FIND_OBJECT_INT(&peers, &value->var, sub);
+ if (t != NULL)
+ return (SNMP_ERR_NOT_WRITEABLE);
+ return (SNMP_ERR_NO_CREATION);
+
+ case SNMP_OP_COMMIT:
+ case SNMP_OP_ROLLBACK:
+ default:
+ abort();
+ }
+
+ /*
+ * Come here for GET and COMMIT
+ */
+ switch (which) {
+
+ case LEAF_ntpFilterValidEntries:
+ value->v.integer = t->filt_entries;
+ break;
+
+ default:
+ abort();
+ }
+ return (SNMP_ERR_NOERROR);
+}
+
+int
+op_ntpFilterRegisterTable(struct snmp_context *ctx __unused, struct snmp_value *value __unused,
+ u_int sub __unused, u_int iidx __unused, enum snmp_op op __unused)
+{
+ asn_subid_t which = value->var.subs[sub - 1];
+ uint32_t peer;
+ uint32_t filt;
+ struct filt *t;
+
+ if (this_tick > peers_tick) {
+ if (fetch_peers() == -1)
+ return (SNMP_ERR_GENERR);
+ peers_tick = this_tick;
+ }
+
+ switch (op) {
+
+ case SNMP_OP_GETNEXT:
+ t = NEXT_OBJECT_OID(&filts, &value->var, sub);
+ if (t == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ index_append(&value->var, sub, &t->index);
+ break;
+
+ case SNMP_OP_GET:
+ t = FIND_OBJECT_OID(&filts, &value->var, sub);
+ if (t == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ break;
+
+ case SNMP_OP_SET:
+ if (index_decode(&value->var, sub, iidx, &peer, &filt))
+ return (SNMP_ERR_NO_CREATION);
+ t = FIND_OBJECT_OID(&filts, &value->var, sub);
+ if (t != NULL)
+ return (SNMP_ERR_NOT_WRITEABLE);
+ return (SNMP_ERR_NO_CREATION);
+
+ case SNMP_OP_COMMIT:
+ case SNMP_OP_ROLLBACK:
+ default:
+ abort();
+ }
+
+ /*
+ * Come here for GET and COMMIT
+ */
+ switch (which) {
+
+ case LEAF_ntpFilterPeersOffset:
+ return (string_get(value, t->offset, -1));
+
+ case LEAF_ntpFilterPeersDelay:
+ return (string_get(value, t->delay, -1));
+
+ case LEAF_ntpFilterPeersDispersion:
+ return (string_get(value, t->dispersion, -1));
+
+ default:
+ abort();
+ }
+ return (SNMP_ERR_NOERROR);
+}
+
+/*
+ * System variables - read-only scalars only.
+ */
+int
+op_begemot_ntp(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];
+ int ret;
+
+ switch (op) {
+
+ case SNMP_OP_GETNEXT:
+ abort();
+
+ case SNMP_OP_GET:
+ switch (which) {
+
+ case LEAF_begemotNtpHost:
+ return (string_get(value, ntp_host, -1));
+
+ case LEAF_begemotNtpPort:
+ return (string_get(value, ntp_port, -1));
+
+ case LEAF_begemotNtpTimeout:
+ value->v.uint32 = ntp_timeout;
+ return (SNMP_ERR_NOERROR);
+
+ case LEAF_begemotNtpDebug:
+ value->v.uint32 = ntp_debug;
+ return (SNMP_ERR_NOERROR);
+
+ case LEAF_begemotNtpJitter:
+ if (this_tick > sysinfo_tick) {
+ if (fetch_sysinfo() == -1)
+ return (SNMP_ERR_GENERR);
+ sysinfo_tick = this_tick;
+ }
+ if (!sysb_jitter)
+ return (SNMP_ERR_NOSUCHNAME);
+ value->v.counter64 = sys_jitter / 1000 * (1ULL << 32);
+ return (SNMP_ERR_NOERROR);
+
+ case LEAF_begemotNtpStability:
+ if (this_tick > sysinfo_tick) {
+ if (fetch_sysinfo() == -1)
+ return (SNMP_ERR_GENERR);
+ sysinfo_tick = this_tick;
+ }
+ if (!sysb_stability)
+ return (SNMP_ERR_NOSUCHNAME);
+ value->v.counter64 = sys_stability * (1ULL << 32);
+ return (SNMP_ERR_NOERROR);
+ }
+ abort();
+
+ case SNMP_OP_SET:
+ switch (which) {
+
+ case LEAF_begemotNtpHost:
+ /* only at initialisation */
+ if (community != COMM_INITIALIZE)
+ return (SNMP_ERR_NOT_WRITEABLE);
+
+ if ((ret = string_save(value, ctx, -1, &ntp_host))
+ != SNMP_ERR_NOERROR)
+ return (ret);
+ return (SNMP_ERR_NOERROR);
+
+ case LEAF_begemotNtpPort:
+ /* only at initialisation */
+ if (community != COMM_INITIALIZE)
+ return (SNMP_ERR_NOT_WRITEABLE);
+
+ if ((ret = string_save(value, ctx, -1, &ntp_port))
+ != SNMP_ERR_NOERROR)
+ return (ret);
+ return (SNMP_ERR_NOERROR);
+
+ case LEAF_begemotNtpTimeout:
+ ctx->scratch->int1 = ntp_timeout;
+ if (value->v.uint32 < 1)
+ return (SNMP_ERR_WRONG_VALUE);
+ ntp_timeout = value->v.integer;
+ return (SNMP_ERR_NOERROR);
+
+ case LEAF_begemotNtpDebug:
+ ctx->scratch->int1 = ntp_debug;
+ ntp_debug = value->v.integer;
+ return (SNMP_ERR_NOERROR);
+ }
+ abort();
+
+ case SNMP_OP_ROLLBACK:
+ switch (which) {
+
+ case LEAF_begemotNtpHost:
+ string_rollback(ctx, &ntp_host);
+ return (SNMP_ERR_NOERROR);
+
+ case LEAF_begemotNtpPort:
+ string_rollback(ctx, &ntp_port);
+ return (SNMP_ERR_NOERROR);
+
+ case LEAF_begemotNtpTimeout:
+ ntp_timeout = ctx->scratch->int1;
+ return (SNMP_ERR_NOERROR);
+
+ case LEAF_begemotNtpDebug:
+ ntp_debug = ctx->scratch->int1;
+ return (SNMP_ERR_NOERROR);
+ }
+ abort();
+
+ case SNMP_OP_COMMIT:
+ switch (which) {
+
+ case LEAF_begemotNtpHost:
+ string_commit(ctx);
+ return (SNMP_ERR_NOERROR);
+
+ case LEAF_begemotNtpPort:
+ string_commit(ctx);
+ return (SNMP_ERR_NOERROR);
+
+ case LEAF_begemotNtpTimeout:
+ case LEAF_begemotNtpDebug:
+ return (SNMP_ERR_NOERROR);
+ }
+ abort();
+ }
+ abort();
+}