diff options
42 files changed, 4523 insertions, 0 deletions
diff --git a/pysnmp/__init__.py b/pysnmp/__init__.py new file mode 100644 index 00000000..863e0070 --- /dev/null +++ b/pysnmp/__init__.py @@ -0,0 +1 @@ +# PySNMP, version 4 diff --git a/pysnmp/carrier/__init__.py b/pysnmp/carrier/__init__.py new file mode 100644 index 00000000..b8ba4364 --- /dev/null +++ b/pysnmp/carrier/__init__.py @@ -0,0 +1,8 @@ +""" + SNMP framework for Python. + + The pysnmp.mapping sub-package implements various transport mappings + for SNMP. + + Copyright 1999-2004 by Ilya Etingof <ilya@glas.net>. See LICENSE for details. +""" diff --git a/pysnmp/carrier/asyncore/__init__.py b/pysnmp/carrier/asyncore/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/pysnmp/carrier/asyncore/__init__.py diff --git a/pysnmp/carrier/asyncore/base.py b/pysnmp/carrier/asyncore/base.py new file mode 100644 index 00000000..466dfad2 --- /dev/null +++ b/pysnmp/carrier/asyncore/base.py @@ -0,0 +1,75 @@ +"""Defines standard API to asyncore-based transport""" +try: + from sys import version_info +except ImportError: + version_info = ( 0, 0 ) # a really early version +import socket, sys +import asyncore +from pysnmp.carrier import error + +class AbstractSocketTransport(asyncore.dispatcher): + sockFamily = sockType = None + retryCount = 0; retryInterval = 0 + def __init__(self, sock=None, sockMap=None): + if sock is None: + try: + sock = socket.socket(self.sockFamily, self.sockType) + except socket.error, why: + raise error.CarrierError('socket() failed: %s' % why) + # Old asyncore doesn't allow socket_map param in constructor + if version_info < (2, 0): + # Taken from dispatcher.__init__() + self.socket = sock + self.add_channel(sockMap) + self.socket.setblocking(0) + self.connected = 1 + else: + asyncore.dispatcher.__init__(self, sock, sockMap) + + # Old asyncore doesn't allow socket_map param + if version_info < (2, 0): + def add_channel (self, sockMap=None): + if sockMap is None: + sockMap = asyncore.socket_map + sockMap[self] = self + + def del_channel (self, sockMap=None): + if sockMap is None: + sockMap = asyncore.socket_map + if sockMap.has_key(self): + del sockMap[self] + + def registerSocket(self, sockMap=None): + self.del_channel(sockMap) + self.add_channel(sockMap) + + def unregisterSocket(self, sockMap=None): + self.del_channel(sockMap) + + # Public API + + def openClientMode(self, iface=None): + raise error.BadArgumentError('Method not implemented') + + def openServerMode(self, iface=None): + raise error.BadArgumentError('Method not implemented') + + def sendMessage(self, outgoingMessage, transportAddress): + raise error.BadArgumentError('Method not implemented') + + def registerCbFun(self, cbFun): + self._cbFun = cbFun + + def unregisterCbFun(self): + self._cbFun = None + + def closeTransport(self): + self.unregisterCbFun() + self.close() + + # asyncore API + def handle_close(self): raise error.CarrierError( + 'Transport unexpectedly closed' + ) + def handle_error(self): raise + diff --git a/pysnmp/carrier/asyncore/dgram/__init__.py b/pysnmp/carrier/asyncore/dgram/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/pysnmp/carrier/asyncore/dgram/__init__.py diff --git a/pysnmp/carrier/asyncore/dgram/base.py b/pysnmp/carrier/asyncore/dgram/base.py new file mode 100644 index 00000000..f7f8c78a --- /dev/null +++ b/pysnmp/carrier/asyncore/dgram/base.py @@ -0,0 +1,63 @@ +"""Implements asyncore-based generic DGRAM transport""" +from socket import SOCK_DGRAM, error +from errno import EWOULDBLOCK, ECONNRESET, ENOTCONN, ESHUTDOWN +from pysnmp.carrier.asynsock.base import AbstractSocketTransport +from pysnmp.carrier import error + +class DgramSocketTransport(AbstractSocketTransport): + sockType = SOCK_DGRAM + retryCount = 3; retryInterval = 1 + def __init__(self, sock=None, sockMap=None): + self.__outQueue = [] + AbstractSocketTransport.__init__(self, sock, sockMap) + + def openClientMode(self, iface=None): + if iface is not None: + try: + self.socket.bind(iface) + except error, why: + raise error.CarrierError('bind() failed: %s' % why) + return self + + def openServerMode(self, iface): + try: + self.socket.bind(iface) + except error, why: + raise error.CarrierError('bind() failed: %s' % why) + self._iface = iface + return self + + def rewriteAddress(self, transportAddress): return transportAddress + + def sendMessage(self, outgoingMessage, transportAddress): + self.__outQueue.append( + (outgoingMessage, self.rewriteAddress(transportAddress)) + ) + + # asyncore API + def handle_connect(self): pass + def writable(self): return self.__outQueue + def handle_write(self): + outgoingMessage, transportAddress = self.__outQueue.pop() + try: + self.socket.sendto(outgoingMessage, transportAddress) + except error, why: + if why[0] != EWOULDBLOCK: + raise error, why + def readable(self): return 1 + def handle_read(self): + try: + incomingMessage, transportAddress = self.socket.recvfrom(65535) + if not incomingMessage: + self.handle_close() + return + else: + self._cbFun(self, transportAddress, incomingMessage) + return + except error, why: + # winsock sometimes throws ENOTCONN + if why[0] in [ECONNRESET, ENOTCONN, ESHUTDOWN]: + self.handle_close() + return + else: + raise error, why diff --git a/pysnmp/carrier/asyncore/dgram/udp.py b/pysnmp/carrier/asyncore/dgram/udp.py new file mode 100644 index 00000000..98c1efb8 --- /dev/null +++ b/pysnmp/carrier/asyncore/dgram/udp.py @@ -0,0 +1,25 @@ +"""Implements asyncore-based UDP transport domain""" +from socket import AF_INET +from types import TupleType, IntType +from string import atoi +from pysnmp.carrier.asynsock.dgram.base import DgramSocketTransport +from pysnmp.carrier import error + +class UdpSocketTransport(DgramSocketTransport): + sockFamily = AF_INET + defaultPort = 161 + + def rewriteAddress(self, transportAddress): + if type(transportAddress) == TupleType: + if type(transportAddress[1]) != IntType: + try: + return transportAddress[0], atoi(transportAddress[1]) + except ValueError, why: + raise error.BadArgumentError( + 'Cant coerce UDP port number %s: %s' % + (transportAddress[1], why) + ) + else: + return transportAddress[0], transportAddress[1] + else: + return transportAddress, self.defaultPort diff --git a/pysnmp/carrier/asyncore/dgram/unix.py b/pysnmp/carrier/asyncore/dgram/unix.py new file mode 100644 index 00000000..7f4c7999 --- /dev/null +++ b/pysnmp/carrier/asyncore/dgram/unix.py @@ -0,0 +1,14 @@ +"""Implements asyncore-based UNIX transport domain""" +from os import remove +from socket import AF_UNIX +from pysnmp.carrier.asynsock.dgram.base import DgramSocketTransport + +class UnixDgramSocketTransport(DgramSocketTransport): + sockFamily = AF_UNIX + + def closeTransport(self): + DgramSocketTransport.closeTransport(self) + try: + remove(self._iface) + except: + pass diff --git a/pysnmp/carrier/asyncore/dispatch.py b/pysnmp/carrier/asyncore/dispatch.py new file mode 100644 index 00000000..1403fef7 --- /dev/null +++ b/pysnmp/carrier/asyncore/dispatch.py @@ -0,0 +1,62 @@ +try: + from sys import version_info +except ImportError: + version_info = ( 0, 0 ) # a really early version +from time import time +from select import select +from pysnmp.carrier.base import AbstractTransportDispatcher + +__all__ = [ 'AsynsockDispatcher' ] + +# Old asyncore doesn't allow socket_map param at poll +if version_info < (2, 0): + def poll(timeout, socket_map): + if not socket_map: + return + sockets = socket_map.keys() + r = filter(lambda x: x.readable(), sockets) + w = filter(lambda x: x.writable(), sockets) + + (r,w,e) = select(r, w, [], timeout) + + for x in r: + try: + x.handle_read_event() + except: + x.handle_error() + for x in w: + try: + x.handle_write_event() + except: + x.handle_error() +else: + from asyncore import poll + +class AsynsockDispatcher(AbstractTransportDispatcher): + """Implements I/O over asynchronous sockets""" + def __init__(self, **kwargs): + self.__sockMap = {} + self.timeout = 1.0 + apply(AbstractTransportDispatcher.__init__, [self], kwargs) + + def registerTransports(self, **kwargs): + apply(AbstractTransportDispatcher.registerTransports, (self,), kwargs) + for transport in kwargs.values(): + transport.registerSocket(self.__sockMap) + + def unregisterTransports(self, *args): + for name in args: + self.getTransport(name).unregisterSocket(self.__sockMap) + apply( + AbstractTransportDispatcher.unregisterTransports, (self, ) + args + ) + + def runDispatcher(self, liveForever=1): + self.doDispatchFlag = liveForever + while 1: + poll(self.timeout, self.__sockMap) + self.handleTimerTick(time()) + if not self.doDispatchFlag: + break + +# XXX doDispatchFlag is needed? diff --git a/pysnmp/carrier/base.py b/pysnmp/carrier/base.py new file mode 100644 index 00000000..a0915048 --- /dev/null +++ b/pysnmp/carrier/base.py @@ -0,0 +1,105 @@ +"""Abstract I/O dispatcher. Defines standard dispatcher API""" +from pysnmp.carrier import error + +class AbstractTransportDispatcher: + def __init__(self, **kwargs): + self.doDispatchFlag = 1 + self.__transports = {} + self.__recvCbFun = self.__timerCbFun = None + apply(self.registerTransports, [], kwargs) + + def _cbFun(self, incomingTransport, transportAddress, incomingMessage): + for name, transport in self.__transports.items(): + if transport is incomingTransport: + transportDomain = name + break + else: + raise error.BadArgumentError( + 'Unregistered transport %s' % incomingTransport + ) + if self.__recvCbFun is None: + raise error.BadArgumentError( + 'Receive callback not registered -- loosing incoming event' + ) + self.__recvCbFun( + self, transportDomain, transportAddress, incomingMessage + ) + + # Dispatcher API + + def registerRecvCbFun(self, recvCbFun): + if self.__recvCbFun is not None: + raise error.BadArgumentError( + 'Receive callback already registered: %s' % self.__recvCbFun + ) + self.__recvCbFun = recvCbFun + + def unregisterRecvCbFun(self): + self.__recvCbFun = None + + def registerTimerCbFun(self, timerCbFun): + if self.__timerCbFun is not None: + raise error.BadArgumentError( + 'Callback already registered: %s' % self.__timerCbFun + ) + self.__timerCbFun = timerCbFun + + def unregisterTimerCbFun(self): + self.__timerCbFun = None + + def closeTransports(self, *args): + if not args: args = self.__transports.keys() + for name in args: + if not self.__transports.has_key(name): + raise error.BadArgumentError( + 'Transport %s not registered' % name + ) + self.__transports[name].closeTransport() + + def registerTransports(self, **kwargs): + for name, transport in kwargs.items(): + if self.__transports.has_key(name): + raise error.BadArgumentError( + 'Transport %s already registered' % name + ) + transport.registerCbFun(self._cbFun) + self.__transports[name] = transport + + def unregisterTransports(self, *args): + if not args: args = self.__transports.keys() + for name in args: + if not self.__transports.has_key(name): + raise error.BadArgumentError( + 'Transport %s not registered' % name + ) + self.__transports[name].unregisterCbFun() + del self.__transports[name] + + def getTransport(self, transportDomain): + return self.__transports.get(transportDomain) + + def sendMessage( + self, outgoingMessage, transportDomain, transportAddress + ): + transport = self.__transports.get(transportDomain) + if transport is None: + raise error.BadArgumentError( + 'No suitable transport domain for %s' % transportDomain + ) + transport.sendMessage(outgoingMessage, transportAddress) + + def handleTimerTick(self, timeNow): + if self.__timerCbFun: + self.__timerCbFun(timeNow) + + def runDispatcher(self, timeout=0.0): + raise error.BadArgumentError('Method not implemented') + + def closeDispatcher(self): + self.closeTransports() + self.unregisterTransports() + self.unregisterRecvCbFun() + self.unregisterTimerCbFun() + +# XXX +# support mapping API? diff --git a/pysnmp/carrier/error.py b/pysnmp/carrier/error.py new file mode 100644 index 00000000..35741156 --- /dev/null +++ b/pysnmp/carrier/error.py @@ -0,0 +1,5 @@ +"""Carrier exceptions""" +from pysnmp import error + +class CarrierError(error.PySnmpError): pass +class BadArgumentError(CarrierError): pass diff --git a/pysnmp/error.py b/pysnmp/error.py new file mode 100644 index 00000000..fcfdf226 --- /dev/null +++ b/pysnmp/error.py @@ -0,0 +1,12 @@ +# Top-level exception class +class PySnmpError(Exception): + def __init__(self, why=None): + Exception.__init__(self) + self.why = why + def __str__(self): return str(self.why) + def __repr__(self): return self.__class__.__name__ + '(' + repr(self.why) + ')' + def __nonzero__(self): + if self.why: return 1 + else: return 0 + +class PySnmpVersionError(PySnmpError): pass diff --git a/pysnmp/proto/__init__.py b/pysnmp/proto/__init__.py new file mode 100644 index 00000000..03f2f1be --- /dev/null +++ b/pysnmp/proto/__init__.py @@ -0,0 +1,7 @@ +""" + SNMP framework for Python. + + The pysnmp.proto sub-package implements various SNMP protocols. + + Copyright 1999-2004 by Ilya Etingof <ilya@glas.net>. See LICENSE for details. +""" diff --git a/pysnmp/proto/error.py b/pysnmp/proto/error.py new file mode 100644 index 00000000..caabc9bf --- /dev/null +++ b/pysnmp/proto/error.py @@ -0,0 +1,12 @@ +from pysnmp import error + +class ProtoError(error.PySnmpError): pass +class BadArgumentError(ProtoError): pass + +# SNMP v3 exceptions + +class SnmpV3Error(ProtoError): pass +class CacheExpiredError(SnmpV3Error): pass +class InternalError(SnmpV3Error): pass +class MessageProcessingError(SnmpV3Error): pass +class RequestTimeout(SnmpV3Error): pass diff --git a/pysnmp/proto/rfc1155.py b/pysnmp/proto/rfc1155.py new file mode 100644 index 00000000..30fbc13b --- /dev/null +++ b/pysnmp/proto/rfc1155.py @@ -0,0 +1,131 @@ +"""Implementation of data types defined by SNMP SMI (RFC1155, RFC1212)""" +from string import split, atoi, atoi_error +from types import StringType +from pysnmp.asn1 import univ, tags, subtypes +import pysnmp.asn1.encoding.ber +from pysnmp.proto import error + +__all__ = [ + 'Integer', 'OctetString', 'Null', 'ObjectIdentifier', + 'IpAddress', 'Counter', 'Gauge', 'TimeTicks', 'Opaque', + 'Sequence', 'SequenceOf', 'Choice', 'NetworkAddress', + 'ObjectName', 'SimpleSyntax', 'ApplicationSyntax', 'ObjectSyntax' + ] + +# SimpleSyntax + +Integer = univ.Integer +OctetString = univ.OctetString +Null = univ.Null +ObjectIdentifier = univ.ObjectIdentifier + +# ApplicationSyntax + +class IpAddressInterfaceMixIn: + def _iconv(self, value): + # Convert IP address given in dotted notation into an unsigned + # int value + try: + packed = split(value, '.') + + except: + raise error.BadArgumentError( + 'Malformed IP address %s for %s' % + (str(value), self.__class__.__name__) + ) + + # Make sure it is four octets length + if len(packed) != 4: + raise error.BadArgumentError( + 'Malformed IP address %s for %s' % + (str(value), self.__class__.__name__) + ) + + # Convert string octets into integer counterparts + try: + return reduce(lambda x, y: x+y, \ + map(lambda x: chr(atoi(x)), packed)) + + except atoi_error: + raise error.BadArgumentError( + 'Malformed IP address %s for %s' % + (str(value), self.__class__.__name__) + ) + + def _oconv(self, value): + if value: + # Convert unsigned int value into IP address dotted representation + return '%d.%d.%d.%d' % (ord(value[0]), ord(value[1]), \ + ord(value[2]), ord(value[3])) + else: return value + +class IpAddress(IpAddressInterfaceMixIn, univ.OctetString): + tagSet = univ.OctetString.tagSet.clone( + tagClass=tags.tagClassApplication, tagId=0x00 + ) + # Subtyping -- size constraint + subtypeConstraints = ( subtypes.ValueSizeConstraint(4, 4), ) + initialValue = '\000\000\000\000' + +class Counter(univ.Integer): + tagSet = univ.Integer.tagSet.clone( + tagClass=tags.tagClassApplication, tagId=0x01 + ) + # Subtyping -- value range constraint + subtypeConstraints = ( subtypes.ValueRangeConstraint(0, 4294967295L), ) + +class Gauge(univ.Integer): + tagSet = univ.Integer.tagSet.clone( + tagClass=tags.tagClassApplication, tagId=0x02 + ) + # Subtyping -- value range constraint + subtypeConstraints = ( subtypes.ValueRangeConstraint(0, 4294967295L), ) + +class TimeTicks(univ.Integer): + tagSet = univ.Integer.tagSet.clone( + tagClass=tags.tagClassApplication, tagId=0x03 + ) + # Subtyping -- value range constraint + subtypeConstraints = ( subtypes.ValueRangeConstraint(0, 4294967295L), ) + +class Opaque(univ.OctetString): + tagSet = univ.OctetString.tagSet.clone( + tagClass=tags.tagClassApplication, tagId=0x04 + ) + +Sequence = univ.Sequence +SequenceOf = univ.SequenceOf +Choice = univ.Choice + +class NetworkAddress(univ.Choice): + protoComponents = { 'internet': IpAddress() } + + # Initialize to Internet address + initialComponentKey = 'internet' + +ObjectName = univ.ObjectIdentifier + +class SimpleSyntax(univ.Choice): + protoComponents = { + 'number': Integer(), + 'string': OctetString(), + 'object': ObjectIdentifier(), + 'empty': Null() + } + initialComponentKey = 'empty' + +class ApplicationSyntax(univ.Choice): + protoComponents = { + 'address': NetworkAddress(), + 'counter': Counter(), + 'gauge': Gauge(), + 'ticks': TimeTicks(), + 'arbitrary': Opaque() + } + +class ObjectSyntax(univ.Choice): + protoComponents = { + 'simple': SimpleSyntax(), + 'application_wide': ApplicationSyntax(), + } + initialComponentKey = 'simple' diff --git a/pysnmp/proto/rfc1157.py b/pysnmp/proto/rfc1157.py new file mode 100644 index 00000000..fe8d5819 --- /dev/null +++ b/pysnmp/proto/rfc1157.py @@ -0,0 +1,158 @@ +"""Implementation of SNMP v.1 (RFC1157)""" +from time import time +from pysnmp.asn1 import univ, tags, subtypes +from pysnmp.proto import rfc1155, error +import pysnmp.asn1.error + +__all__ = [ + 'Version', 'Community', 'RequestId', 'ErrorStatus', 'ErrorIndex', + 'VarBind', 'VarBindList', 'GetRequestPdu', 'GetNextRequestPdu', + 'GetResponsePdu', 'SetRequestPdu', 'Enterprise', 'AgentAddr', + 'GenericTrap', 'SpecificTrap', 'TimeStamp', 'TrapPdu', 'Pdus', + 'Message' + ] + +class Version(univ.Integer): + subtypeConstraints = ( subtypes.SingleValueConstraint(0), ) + initialValue = 0 + namedValues = univ.Integer.namedValues.clone(('version-1', 0)) + +class Community(univ.OctetString): + initialValue = 'public' + +class InitialRequestIdMixIn: + # Singular source of req IDs + globalRequestId = 1000 - long(((time() / 100) % 1) * 1000) + def initialValue(self): + try: + self.set(InitialRequestIdMixIn.globalRequestId) + except pysnmp.asn1.error.ValueConstraintError: + self.set(InitialRequestIdMixIn.globalRequestId) + else: + InitialRequestIdMixIn.globalRequestId = InitialRequestIdMixIn.globalRequestId + 1 + +class RequestId(InitialRequestIdMixIn, univ.Integer): pass + +class ErrorStatus(univ.Integer): + initialValue = 0 + subtypeConstraints = ( subtypes.ValueRangeConstraint(0, 5), ) + namedValues = univ.Integer.namedValues.clone( + ('noError', 0), ('tooBig', 1), ('noSuchName', 2), + ('badValue', 3), ('readOnly', 4), ('genError', 5) + ) + pduErrors = [ + '(noError) No Error', + '(tooBig) Response message would have been too large', + '(noSuchName) There is no such variable name in this MIB', + '(badValue) The value given has the wrong type or length', + '(readOnly) No modifications allowed to this object', + '(genError) A general failure occured' + ] + + def __str__(self): + return '%s: %d (%s)' % ( + self.__class__.__name__, self.get(), self.pduErrors[self.get()] + ) + +class ErrorIndex(univ.Integer): + initialValue = 0 + +class VarBind(univ.Sequence): + # Bind structure + protoComponents = { + 'name': rfc1155.ObjectName(), + 'value': rfc1155.ObjectSyntax() + } + protoSequence = ( 'name', 'value' ) + +class VarBindList(univ.SequenceOf): + protoComponent = VarBind() + +class RequestPdu(univ.Sequence): + tagSet = univ.Sequence.tagSet.clone( + tagClass=tags.tagClassContext + ) + # PDU structure + protoComponents = { + 'request_id': RequestId(), + 'error_status': ErrorStatus(), + 'error_index': ErrorIndex(), + 'variable_bindings': VarBindList() + } + protoSequence = ( + 'request_id', 'error_status', 'error_index', 'variable_bindings' + ) + +class GetRequestPdu(RequestPdu): + tagSet = RequestPdu.tagSet.clone(tagId=0x00) + +class GetNextRequestPdu(RequestPdu): + tagSet = RequestPdu.tagSet.clone(tagId=0x01) + +class GetResponsePdu(RequestPdu): + tagSet = RequestPdu.tagSet.clone(tagId=0x02) + +class SetRequestPdu(RequestPdu): + tagSet = RequestPdu.tagSet.clone(tagId=0x03) + +# Trap stuff + +class Enterprise(univ.ObjectIdentifier): + initialValue = (1,3,6,1,1,2,3,4,1) + +class AgentAddr(rfc1155.NetworkAddress): pass + +class GenericTrap(univ.Integer): + initialValue = 0 + subtypeConstraints = ( subtypes.ValueRangeConstraint(0, 6), ) + namedValues = univ.Integer.namedValues.clone( + ('coldStart', 0), ('warmStart', 1), ('linkDown', 2), + ('linkUp', 3), ('authenticationFailure', 4), ('egpNeighborLoss', 5), + ('enterpriseSpecific', 6) + ) + +class SpecificTrap(univ.Integer): + initialValue = 0 + +class TimeStamp(rfc1155.TimeTicks): + def __init__(self, value=int(time())): + rfc1155.TimeTicks.__init__(self, value) + +class TrapPdu(univ.Sequence): + tagSet = univ.Sequence.tagSet.clone( + tagClass=tags.tagClassContext, tagId=0x04 + ) + # PDU structure + protoComponents = { + 'enterprise': Enterprise(), + 'agent_addr': AgentAddr(), + 'generic_trap': GenericTrap(), + 'specific_trap': SpecificTrap(), + 'time_stamp': TimeStamp(), + 'variable_bindings': VarBindList() + } + protoSequence = ( + 'enterprise', 'agent_addr', 'generic_trap', + 'specific_trap', 'time_stamp', 'variable_bindings' + ) + +class Pdus(univ.Choice): + protoComponents = { + 'get_request': GetRequestPdu(), + 'get_next_request': GetNextRequestPdu(), + 'get_response': GetResponsePdu(), + 'set_request': SetRequestPdu(), + 'trap': TrapPdu() + } + protoSequence = ( + 'get_request', 'get_next_request', 'get_response', + 'set_request', 'trap' + ) + +class Message(univ.Sequence): + protoComponents = { + 'version': Version(), + 'community': Community(), + 'pdu': Pdus() + } + protoSequence = ( 'version', 'community', 'pdu' ) diff --git a/pysnmp/proto/rfc1902.py b/pysnmp/proto/rfc1902.py new file mode 100644 index 00000000..fb4b55ab --- /dev/null +++ b/pysnmp/proto/rfc1902.py @@ -0,0 +1,159 @@ +"""Implementation of data types defined by SNMP SMI (RFC1902)""" +from string import join +from pysnmp.proto import rfc1155, error +from pysnmp.asn1 import univ, tags, subtypes, namedval + +__all__ = [ + 'Integer', 'Integer32', 'OctetString', 'Null', 'ObjectIdentifier', + 'IpAddress', 'Counter32', 'Gauge32', 'Unsigned32', 'TimeTicks', + 'Opaque', 'Counter64', 'Sequence', 'Bits', 'SequenceOf', 'Choice', + 'ObjectName', 'SimpleSyntax', 'ApplicationSyntax', 'ObjectSyntax' + ] + +# SimpleSyntax + +class Integer(univ.Integer): + # Subtyping -- value range constraint + subtypeConstraints = ( + subtypes.ValueRangeConstraint(-2147483648L, 2147483647L), + ) + +class Integer32(univ.Integer): + # Subtyping -- value range constraint + subtypeConstraints = ( + subtypes.ValueRangeConstraint(-2147483648L, 2147483647L), + ) + +class OctetString(univ.OctetString): + # Subtyping -- size constraint + subtypeConstraints = ( subtypes.ValueSizeConstraint(0, 65535), ) + +Null = univ.Null +ObjectIdentifier = univ.ObjectIdentifier + +# ApplicationSyntax + +class IpAddress(rfc1155.IpAddressInterfaceMixIn, univ.OctetString): + tagSet = univ.OctetString.tagSet.clone( + tagClass=tags.tagClassApplication, tagId=0x00 + ) + # Subtyping -- size constraint + subtypeConstraints = ( subtypes.ValueSizeConstraint(4, 4), ) + initialValue = '\000\000\000\000' + +class Counter32(univ.Integer): + tagSet = univ.Integer.tagSet.clone( + tagClass=tags.tagClassApplication, tagId=0x01 + ) + # Subtyping -- value range constraint + subtypeConstraints = ( subtypes.ValueRangeConstraint(0, 4294967295L), ) + +class Gauge32(univ.Integer): + tagSet = univ.Integer.tagSet.clone( + tagClass=tags.tagClassApplication, tagId=0x02 + ) + # Subtyping -- value range constraint + subtypeConstraints = ( subtypes.ValueRangeConstraint(0, 4294967295L), ) + +class Unsigned32(univ.Integer): + tagSet = univ.Integer.tagSet.clone( + tagClass=tags.tagClassApplication, tagId=0x02 + ) + # Subtyping -- value range constraint + subtypeConstraints = ( subtypes.ValueRangeConstraint(0, 4294967295L), ) + +class TimeTicks(univ.Integer): + tagSet = univ.Integer.tagSet.clone( + tagClass=tags.tagClassApplication, tagId=0x03 + ) + # Subtyping -- value range constraint + subtypeConstraints = ( subtypes.ValueRangeConstraint(0, 4294967295L), ) + +class Opaque(univ.OctetString): + tagSet = univ.OctetString.tagSet.clone( + tagClass=tags.tagClassApplication, tagId=0x04 + ) + +class Counter64(univ.Integer): + tagSet = univ.Integer.tagSet.clone( + tagClass=tags.tagClassApplication, tagId=0x06 + ) + # Subtyping -- value range constraint + subtypeConstraints = ( + subtypes.ValueRangeConstraint(0, 18446744073709551615L), + ) + +class Bits(univ.OctetString): + namedValues = namedval.NamedValues() + + def _iconv(self, bits): + octets = [] + for bit in bits: + v = self.namedValues.getValue(bit) + if v is None: + raise error.BadArgumentError( + 'Unknown named bit %s' % bit + ) + d, m = divmod(v, 8) + if d >= len(octets): + octets.extend((0,) * (d - len(octets) + 1)) + octets[d] = octets[d] | 0x01 << (7-m) + return join(map(lambda x: chr(x), octets)) + + def _oconv(self, value): + names = [] + octets = tuple(map(None, value)) + i = 0 + while i < len(octets): + v = ord(octets[i]) + j = 7 + while j > 0: + if v & (0x01<<j): + name = self.namedValues.getName(i*8+7-j) + if name is None: + raise error.BadArgumentError( + 'Unknown named value %s' % v + ) + names.append(name) + j = j - 1 + i = i + 1 + return tuple(names) + + def addNamedValues(self, *namedValues): + self.namedValues = apply(self.namedValues.clone, namedValues) + return self + + def clone(self, value=None): + myClone = univ.OctetString.clone(self, value) + myClone.namedValues = self.namedValues + return myClone + +Sequence = univ.Sequence +SequenceOf = univ.SequenceOf +Choice = univ.Choice + +class ObjectName(ObjectIdentifier): pass + +class SimpleSyntax(univ.Choice): + protoComponents = { + 'integer_value': Integer(), + 'string_value': OctetString(), + 'objectID_value': ObjectIdentifier() + } + +class ApplicationSyntax(univ.Choice): + protoComponents = { + 'ipAddress_value': IpAddress(), + 'counter_value': Counter32(), + 'timeticks_value': TimeTicks(), + 'arbitrary_value': Opaque(), + 'big_counter_value': Counter64(), + 'unsigned_integer_value': Unsigned32(), + 'gauge32_value': Gauge32(), + } # BITS misplaced? + +class ObjectSyntax(univ.Choice): + protoComponents = { + 'simple_syntax': SimpleSyntax(), + 'application_syntax': ApplicationSyntax(), + } diff --git a/pysnmp/proto/rfc1905.py b/pysnmp/proto/rfc1905.py new file mode 100644 index 00000000..cc5f53a1 --- /dev/null +++ b/pysnmp/proto/rfc1905.py @@ -0,0 +1,204 @@ +"""Implementation of SNMP v.2c (RFC1905)""" + +from time import time +from pysnmp.asn1 import univ, tags, subtypes +from pysnmp.proto import rfc1902 +from pysnmp.proto.rfc1157 import InitialRequestIdMixIn +import pysnmp.asn1.error + +__all__ = [ + 'Version', 'Community', 'RequestId', 'NoSuchObject', + 'NoSuchInstance', 'EndOfMibView', 'BindValue', 'VarBind', + 'VarBindList', 'Pdu', 'NonRepeaters', 'MaxRepetitions', + 'GetRequestPdu', 'GetNextRequestPdu', 'ResponsePdu', + 'SetRequestPdu', 'GetBulkRequestPdu', 'InformRequestPdu', + 'SnmpV2TrapPdu', 'ReportPdu', 'Pdus', 'Message' + ] + +# Value reference -- max bindings in VarBindList +max_bindings = rfc1902.Integer(2147483647) + +class Version(univ.Integer): + subtypeConstraints = ( subtypes.SingleValueConstraint(1), ) + initialValue = 1 + namedValues = univ.Integer.namedValues.clone(('version-2c', 1)) + +class Community(univ.OctetString): + initialValue = 'public' + +class RequestId(InitialRequestIdMixIn, rfc1902.Integer32): pass + +class ErrorStatus(univ.Integer): + initialValue = 0 + subtypeConstraints = ( subtypes.ValueRangeConstraint(0, 18), ) + namedValues = univ.Integer.namedValues.clone( + ('noError', 0), ('tooBig', 1), ('noSuchName', 3), ('badValue', 4), + ('readOnly', 5), ('genError', 6), ('noAccess', 7), ('wrongType', 8), + ('wrongLength', 9), ('wrongEncoding', 10), ('wrongValue', 11), + ('noCreation', 12), ('inconsistentValue', 13), + ('resourceUnavailable', 14), ('commitFailed', 15), ('undoFailed', 16), + ('authorizationError', 17), ('notWritable', 18), + ('inconsistentName', 19) + ) + pduErrors = [ + '(noError) No Error', + '(tooBig) Response message would have been too large', + '(noSuchName) There is no such variable name in this MIB', + '(badValue) The value given has the wrong type or length', + '(readOnly) No modifications allowed to this object', + '(genError) A general failure occured', + '(noAccess) Access denied', + '(wrongType) Wrong BER type', + '(wrongLength) Wrong BER length', + '(wrongEncoding) Wrong BER encoding', + '(wrongValue) Wrong value', + '(noCreation) Object creation prohibited', + '(inconsistentValue) Inconsistent value', + '(resourceUnavailable) Resource unavailable', + '(commitFailed) Commit failed', + '(undoFailed) Undo failed', + '(authorizationError) Authorization error', + '(notWritable) Object is not writable', + '(inconsistentName) Inconsistent object name' + ] + + def __str__(self): + return '%s: %d (%s)' % ( + self.__class__.__name__, self.get(), self.pduErrors[self.get()] + ) + +class ErrorIndex(univ.Integer): + subtypeConstraints = ( + subtypes.ValueRangeConstraint(0, max_bindings.get()), + ) + +class NoSuchObject(univ.Null): + tagSet = univ.Null.tagSet.clone( + tagClass=tags.tagClassContext, tagId=0x00 + ) + +class NoSuchInstance(univ.Null): + tagSet = univ.Null.tagSet.clone( + tagClass=tags.tagClassContext, tagId=0x01 + ) + +class EndOfMibView(univ.Null): + tagSet = univ.Null.tagSet.clone( + tagClass=tags.tagClassContext, tagId=0x02 + ) + +class BindValue(univ.Choice): + protoComponents = { + 'value': rfc1902.ObjectSyntax(), + 'unspecified': rfc1902.Null(), + 'noSuchObject': NoSuchObject(), + 'noSuchInstance': NoSuchInstance(), + 'endOfMibView': EndOfMibView() + } + initialComponentKey = 'unspecified' + +class VarBind(univ.Sequence): + # Bind structure + protoComponents = { + 'name': rfc1902.ObjectName(), + 'value': BindValue() + } + protoSequence = ( 'name', 'value' ) + +class VarBindList(univ.SequenceOf): + protoComponent = VarBind() + subtypeConstraints = ( + subtypes.ValueSizeConstraint(0, max_bindings.get()), + ) + +# Base class for a non-bulk PDU +class Pdu(univ.Sequence): + tagSet = univ.Sequence.tagSet.clone( + tagClass=tags.tagClassContext + ) + # PDU structure + protoComponents = { + 'request_id': RequestId(), + 'error_status': ErrorStatus(), + 'error_index': ErrorIndex(), + 'variable_bindings': VarBindList() + } + protoSequence = ( + 'request_id', 'error_status', + 'error_index', 'variable_bindings' + ) + +class NonRepeaters(univ.Integer): + subtypeConstraints = ( + subtypes.ValueRangeConstraint(0, max_bindings.get()), + ) + +class MaxRepetitions(univ.Integer): + subtypeConstraints = ( + subtypes.ValueRangeConstraint(0, max_bindings.get()), + ) + initialValue = 255 + +# Base class for bulk PDU +class BulkPdu(univ.Sequence): + tagSet = univ.Sequence.tagSet.clone( + tagClass=tags.tagClassContext + ) + # PDU structure + protoComponents = { + 'request_id': RequestId(), + 'non_repeaters': NonRepeaters(), + 'max_repetitions': MaxRepetitions(), + 'variable_bindings': VarBindList() + } + protoSequence = ( + 'request_id', 'non_repeaters', + 'max_repetitions', 'variable_bindings' + ) + +class GetRequestPdu(Pdu): + tagSet = Pdu.tagSet.clone(tagId=0x00) + +class GetNextRequestPdu(Pdu): + tagSet = Pdu.tagSet.clone(tagId=0x01) + +class ResponsePdu(Pdu): + tagSet = Pdu.tagSet.clone(tagId=0x02) + +class SetRequestPdu(Pdu): + tagSet = Pdu.tagSet.clone(tagId=0x03) + +class GetBulkRequestPdu(BulkPdu): + tagSet = BulkPdu.tagSet.clone(tagId=0x05) + +class InformRequestPdu(Pdu): + tagSet = Pdu.tagSet.clone(tagId=0x06) + +class SnmpV2TrapPdu(Pdu): + tagSet = Pdu.tagSet.clone(tagId=0x07) + +# XXX v1 compatible alias +TrapPdu = SnmpV2TrapPdu + +class ReportPdu(Pdu): + tagSet = Pdu.tagSet.clone(tagId=0x08) + +class Pdus(univ.Choice): + protoComponents = { + 'get_request': GetRequestPdu(), + 'get_next_request': GetNextRequestPdu(), + 'get_bulk_request': GetBulkRequestPdu(), + 'response': ResponsePdu(), + 'set_request': SetRequestPdu(), + 'inform_request': InformRequestPdu(), + 'snmpV2_trap': SnmpV2TrapPdu(), + 'report': ReportPdu() + } + +class Message(univ.Sequence): + protoComponents = { + 'version': Version(), + 'community': Community(), + 'pdu': Pdus() + } + protoSequence = ( 'version', 'community', 'pdu' ) diff --git a/pysnmp/proto/rfc3411.py b/pysnmp/proto/rfc3411.py new file mode 100644 index 00000000..5a2f1349 --- /dev/null +++ b/pysnmp/proto/rfc3411.py @@ -0,0 +1,46 @@ +from pysnmp.proto import rfc1157, rfc1905 + +__all__ = [ + 'ReadClassMixIn', 'WriteClassMixIn', 'ResponseClassMixIn', + 'NotificationClassMixIn', 'InternalClassMixIn', + 'ConfirmedClassMixIn', 'UnconfirmedClassMixIn' + ] + +# Functional PDU classification + +class ReadClassMixIn: pass +class WriteClassMixIn: pass +class ResponseClassMixIn: pass +class NotificationClassMixIn: pass +class InternalClassMixIn: pass + +# PDU classification based on whether a response is expected + +class ConfirmedClassMixIn: pass +class UnconfirmedClassMixIn: pass + +# Classify various PDU types + +__mixInMatrix = ( + # RFC1157 types + (rfc1157.GetRequestPdu, (ReadClassMixIn, ConfirmedClassMixIn)), + (rfc1157.GetNextRequestPdu, (ReadClassMixIn, ConfirmedClassMixIn)), + (rfc1157.SetRequestPdu, (WriteClassMixIn, ConfirmedClassMixIn)), + (rfc1157.GetResponsePdu, (ResponseClassMixIn, UnconfirmedClassMixIn)), + (rfc1157.GetResponsePdu, ( ResponseClassMixIn, UnconfirmedClassMixIn)), + (rfc1157.TrapPdu, (NotificationClassMixIn, UnconfirmedClassMixIn)), + # RFC1905 types + (rfc1905.GetRequestPdu, (ReadClassMixIn, ConfirmedClassMixIn)), + (rfc1905.GetNextRequestPdu, (ReadClassMixIn, ConfirmedClassMixIn)), + (rfc1905.GetBulkRequestPdu, (ReadClassMixIn, ConfirmedClassMixIn)), + (rfc1905.SetRequestPdu, (WriteClassMixIn, ConfirmedClassMixIn)), + (rfc1905.ResponsePdu, (ResponseClassMixIn, UnconfirmedClassMixIn)), + (rfc1905.ReportPdu, (ResponseClassMixIn, UnconfirmedClassMixIn, + InternalClassMixIn)), + (rfc1905.SnmpV2TrapPdu, (NotificationClassMixIn, UnconfirmedClassMixIn)) + ) + +for baseClass, mixIns in __mixInMatrix: + for mixIn in mixIns: + if mixIn not in baseClass.__bases__: + baseClass.__bases__ = (mixIn, ) + baseClass.__bases__ diff --git a/pysnmp/proto/rfc3412.py b/pysnmp/proto/rfc3412.py new file mode 100644 index 00000000..4571d49c --- /dev/null +++ b/pysnmp/proto/rfc3412.py @@ -0,0 +1,520 @@ +"""SNMP v3 Message Processing and Dispatching (RFC3412)""" +from pysnmp.smi import builder, instrum +from pysnmp.smi.error import NoSuchInstanceError +from pysnmp.proto import error +from pysnmp.proto.msgproc import rfc2576, demux +from pysnmp.carrier.asynsock.dispatch import AsynsockDispatcher +from pysnmp.carrier.asynsock.dgram.udp import UdpSocketTransport +from pysnmp.error import PySnmpError + +__all__ = [ 'MsgAndPduDispatcher' ] + +# Defaults +defaultMessageProcessingVersion = rfc2576.snmpV1MessageProcessingModelId + +class AbstractApplication: + # Dispatcher registration protocol + contextEngineId = None + # ((pduVersion, pduType), ...) + pduTypes = (()) + + def processPdu(self, dsp, **kwargs): + raise error.BadArgumentError( + 'App %s doesn\'t accept request PDUs' % (self) + ) + def processResponsePdu(self, dsp, **kwargs): + raise error.BadArgumentError( + 'App %s doesn\'t accept response PDUs' % (self) + ) + +class MsgAndPduDispatcher: + """SNMP engine PDU & message dispatcher. Exchanges SNMP PDU's with + applications and serialized messages with transport level. + """ + def __init__(self, transportDispatcher=None, mibInstrumController=None): + self.transportDispatcher = None + + if transportDispatcher is None: + # XXX load all available transports by default + # Default is Manager (client) mode over UDP + self.registerTransportDispatcher( + AsynsockDispatcher(udp=UdpSocketTransport()) + ) + else: + self.registerTransportDispatcher(transportDispatcher) + + if mibInstrumController is None: + self.mibInstrumController = instrum.MibInstrumController( + builder.MibBuilder() + ) + else: + self.mibInstrumController = mibInstrumController + + self.mibInstrumController.mibBuilder.loadModules( + 'SNMP-MPD-MIB', 'SNMP-COMMUNITY-MIB', 'SNMP-TARGET-MIB', + 'SNMP-USER-BASED-SM-MIB' + ) + + # Versions to subsystems mapping + self.messageProcessingSubsystems = { + rfc2576.snmpV1MessageProcessingModelId: + rfc2576.SnmpV1MessageProcessingModel(self.mibInstrumController), + rfc2576.snmpV2cMessageProcessingModelId: + rfc2576.SnmpV2cMessageProcessingModel(self.mibInstrumController), + } + + self.__msgDemuxer = demux.SnmpMsgDemuxer() + + # Registered context engine IDs + self.__appsRegistration = {} + + # Source of sendPduHandle and cache of requesting apps + self.__sendPduHandle = 0L + self.__cacheRepository = {} + + # Register/unregister with transport dispatcher + def registerTransportDispatcher(self, transportDispatcher): + if self.transportDispatcher is not None: + raise error.BadArgumentError( + 'Transport dispatcher already registered' + ) + transportDispatcher.registerRecvCbFun( + self.receiveMessage + ) + transportDispatcher.registerTimerCbFun( + self.__receiveTimerTick + ) + self.transportDispatcher = transportDispatcher + + def unregisterTransportDispatcher(self): + if self.transportDispatcher is None: + raise error.BadArgumentError( + 'Transport dispatcher not registered' + ) + self.transportDispatcher.unregisterRecvCbFun() + self.transportDispatcher.unregisterTimerCbFun() + self.transportDispatcher = None + + # These routines manage cache of management apps + + def __newSendPduHandle(self): + sendPduHandle = self.__sendPduHandle = self.__sendPduHandle + 1 + return sendPduHandle + + def __cacheAdd(self, index, **kwargs): + self.__cacheRepository[index] = kwargs + return index + + def __cachePop(self, index): + cachedParams = self.__cacheRepository.get(index) + if cachedParams is None: + return + del self.__cacheRepository[index] + return cachedParams + + def __cacheUpdate(self, index, **kwargs): + if not self.__cacheRepository.has_key(index): + raise error.BadArgumentError( + 'Cache miss on update for %s' % kwargs + ) + self.__cacheRepository[index].update(kwargs) + + def __cacheExpire(self, cbFun): + for index, cachedParams in self.__cacheRepository.items(): + if cbFun: + if cbFun(cachedParams): + del self.__cacheRepository[index] + + # Application registration with dispatcher + + # 4.3.1 + def registerContextEngineId(self, app): + """Register application with dispatcher""" + # 4.3.2 -> noop + contextEngineId = app.contextEngineId + if contextEngineId is None: + # Default to local snmpEngineId + contextEngineId,= self.mibInstrumController.mibBuilder.importSymbols( + 'SNMP-FRAMEWORK-MIB', 'snmpEngineID' + ) + contextEngineId = contextEngineId.syntax.get() + + # 4.3.3 + for pduVersion, pduType in app.pduTypes: + k = (contextEngineId, pduVersion, pduType) + if self.__appsRegistration.has_key(k): + raise error.BadArgumentError( + 'Duplicate registration %s/%s/%s' % + (contextEngineId, pduVersion, pduType) + ) + + # 4.3.4 + self.__appsRegistration[k] = app + + # 4.4.1 + def unregisterContextEngineId(self, app): + """Unregister application with dispatcher""" + # 4.3.4 + contextEngineId = app.contextEngineId + if contextEngineId is None: + # Default to local snmpEngineId + contextEngineId, = self.mibInstrumController.mibBuilder.importSymbols( + 'SNMP-FRAMEWORK-MIB', 'snmpEngineID' + ).syntax.get() + + for pduVersion, pduType in app.pduTypes: + k = (contextEngineId, pduVersion, pduType) + if self.__appsRegistration.has_key(k): + del self.__appsRegistration[k] + + def getRegisteredApp(self, contextEngineId, pduVersion, pduType): + return self.__appsRegistration.get( + (contextEngineId, pduVersion, pduType) + ) + + # Dispatcher <-> application API + + # 4.1.1 + + def sendPdu(self, **kwargs): + """PDU dispatcher -- prepare and serialize a request or notification""" + # 4.1.1.2 + messageProcessingModel = kwargs.get( + 'messageProcessingModel', defaultMessageProcessingVersion + ) + mpHandler = self.messageProcessingSubsystems.get(messageProcessingModel) + if mpHandler is None: + raise error.BadArgumentError( + 'Unknown messageProcessingModel: %s' % messageProcessingModel + ) + mpInParams = {} + mpInParams.update(kwargs) + + # 4.1.1.3 + mpInParams['sendPduHandle'] = self.__cacheAdd( + self.__newSendPduHandle(), + expectResponse=kwargs.get('expectResponse') + ) + + # 4.1.1.4 & 4.1.1.5 + try: + mpOutParams = apply( + mpHandler.prepareOutgoingMessage, (), mpInParams + ) + except PySnmpError: + if mpInParams.has_key('sendPduHandle'): + self.__cachePop(mpInParams['sendPduHandle']) + raise + + # 4.1.1.6 + self.transportDispatcher.sendMessage( + mpOutParams['wholeMsg'], + mpOutParams['destTransportDomain'], + mpOutParams['destTransportAddress'] + ) + + # Update cache with transport details (used for retrying) + self.__cacheUpdate( + mpInParams['sendPduHandle'], + wholeMsg=mpOutParams['wholeMsg'], + destTransportDomain=mpOutParams['destTransportDomain'], + destTransportAddress=mpOutParams['destTransportAddress'], + sendPduHandle=mpInParams['sendPduHandle'] + ) + + return mpInParams['sendPduHandle'] + + # 4.1.2.1 + def returnResponsePdu(self, **kwargs): + """PDU dispatcher -- prepare and serialize a response""" + # Extract input values and initialize defaults + messageProcessingModel = kwargs.get( + 'messageProcessingModel', defaultMessageProcessingVersion + ) + mpHandler = self.messageProcessingSubsystems.get(messageProcessingModel) + if mpHandler is None: + raise error.BadArgumentError( + 'Unknown messageProcessingModel: %s' % messageProcessingModel + ) + + # 4.1.2.2, 4.1.2.3 + # Defaults + mpInParams = { + 'securityModel': 3, + 'securityName': 'pluto', + 'securityLevel': 'NoAuthNoPriv', + 'pduVersion': defaultMessageProcessingVersion, + 'maxSizeResponseScopedPdu': 65000, + 'messageProcessingModel': messageProcessingModel + } + mpInParams.update(kwargs) + try: + mpOutParams = apply( + mpHandler.prepareResponseMessage, (), mpInParams + ) + except error.ProtoError: + return + + # 4.1.2.4 + self.transportDispatcher.sendMessage( + mpOutParams['wholeMsg'], + mpOutParams['destTransportDomain'], + mpOutParams['destTransportAddress'] + ) + + # 4.2.1 + def receiveMessage( + self, tspDsp, transportDomain, transportAddress, wholeMsg + ): + """Message dispatcher -- de-serialize message into PDU""" + # 4.2.1.1 + snmpInPkts, = self.mibInstrumController.mibBuilder.importSymbols( + 'SNMPv2-MIB', 'snmpInPkts' + ) + snmpInPkts.syntax.inc(1) + + # 4.2.1.2 + try: + restOfMsg = self.__msgDemuxer.decodeItem(wholeMsg) + except PySnmpError: + snmpInAsn1ParseErrs, = self.mibInstrumController.mibBuilder.importSymbols('SNMPv2-MIB', 'snmpInAsn1ParseErrs') + snmpInAsn1ParseErrs.syntax.inc(1) + return '' # n.b the whole buffer gets dropped + messageProcessingModel = self.__msgDemuxer['version'].get() + mpHandler = self.messageProcessingSubsystems.get( + messageProcessingModel + ) + if mpHandler is None: + snmpInBadVersions, = self.mibInstrumController.mibBuilder.importSymbols( + 'SNMPv2-MIB', 'snmpInBadVersions' + ) + snmpInBadVersions.syntax.inc(1) + return restOfMsg + + # 4.2.1.3 -- no-op + + # 4.2.1.4 + try: + mpOutParams = mpHandler.prepareDataElements( + transportDomain=transportDomain, + transportAddress=transportAddress, + wholeMsg=wholeMsg + ) + except error.ProtoError: + return restOfMsg + + # 4.2.2 + if mpOutParams.get('sendPduHandle') is None: + # 4.2.2.1 (request or notification) + + # 4.2.2.1.1 + app = self.getRegisteredApp( + mpOutParams['contextEngineID'], + mpOutParams['pduVersion'], + mpOutParams['pduType'] + ) + + # 4.2.2.1.2 + if app is None: + # 4.2.2.1.2.a + snmpUnknownPDUHandlers, = self.mibInstrumController.mibBuilder.importSymbols('SNMP-MPD-MIB', 'snmpUnknownPDUHandlers') + snmpUnknownPDUHandlers.syntax.inc(1) + + # 4.2.2.1.2.b + statusInformation = { + 'oid': snmpUnknownPDUHandlers.name, + 'value': snmpUnknownPDUHandlers.syntax + } + + mpInParams = { + 'transportDomain': transportDomain, + 'transportAddress': transportAddress + } + mpInParams.update(mpOutParams) + mpInParams['statusInformation'] = statusInformation + try: + mpOutParams = apply( + mpHandler.prepareResponseMessage, (), mpInParams + ) + except error.ProtoError: + return restOfMsg + if mpOutParams.get('result'): # XXX need this? + return restOfMsg + + # 4.2.2.1.2.c + try: + self.transportDispatcher.sendMessage( + mpOutParams['wholeMsg'], + mpOutParams['destTransportDomain'], + mpOutParams['destTransportAddress'] + ) + except PySnmpError: + pass + + # 4.2.2.1.2.d + return restOfMsg + else: + # 4.2.2.1.3 + apply(app.processPdu, (self,), mpOutParams) + return restOfMsg + else: + # 4.2.2.2 (response) + + # 4.2.2.2.1 + cachedParams = self.__cachePop(mpOutParams.get('sendPduHandle')) + + # 4.2.2.2.2 + if cachedParams is None: + snmpUnknownPDUHandlers, = self.mibInstrumController.mibBuilder.importSymbols('SNMP-MPD-MIB', 'snmpUnknownPDUHandlers') + snmpUnknownPDUHandlers.syntax.inc(1) + return restOfMsg + + # 4.2.2.2.3 + # no-op ? XXX + + # 4.2.2.2.4 + apply(cachedParams['expectResponse'].processResponsePdu, + (self,), mpOutParams) + + return restOfMsg + + # Cache expiration stuff + + def __receiveTimerTick(self, timeNow): + def retryRequest(cachedParams, self=self, timeNow=timeNow): + # Initialize retry params + if not cachedParams.has_key('retryCount'): + # Default retry params to transport-specific values + tsp = self.transportDispatcher.getTransport( + cachedParams['destTransportDomain'] + ) + cachedParams['retryCount']=tsp.retryCount + cachedParams['retryInterval']=tsp.retryInterval + # Initialize retry params from MIB table + snmpTargetAddrTAddress, \ + snmpTargetAddrTDomain, \ + snmpTargetAddrRetryCount, \ + snmpTargetAddrTimeout = self.mibInstrumController.mibBuilder.importSymbols( + 'SNMP-TARGET-MIB', + 'snmpTargetAddrTAddress', + 'snmpTargetAddrTDomain', + 'snmpTargetAddrRetryCount', + 'snmpTargetAddrTimeout' + ) + mibNodeIdx = snmpTargetAddrTAddress + while 1: + try: + mibNodeIdx = snmpTargetAddrTAddress.getNextNode( + mibNodeIdx.name + ) + except NoSuchInstanceError: + break + if mibNodeIdx.syntax != cachedParams.get( + 'destTransportAddress' + ): continue + instId = mibNodeIdx.name[len(snmpTargetAddrTAddress.name):] + mibNode = snmpTargetAddrTDomain.getNode( + snmpTargetAddrTDomain.name + instId + ) + if mibNode.syntax != cachedParams.get( + 'destTransportDomain' + ): continue + cachedParams['retryCount'] = snmpTargetAddrRetryCount.getNode(snmpTargetAddrRetryCount.name + instId) + cachedParams['retryInterval'] = snmpTargetAddrTimeout.getNode(snmpTargetAddrTimeout.name + instId) + break + # Fail timed-out requests + if cachedParams['retryCount'] == 0: + cachedParams['expectResponse'].processResponsePdu( + self, + statusInformation = { + 'errorIndication': error.RequestTimeout() + }, + sendPduHandle=cachedParams['sendPduHandle'] + ) + return 1 + # Re-calculate resend time + if not cachedParams.has_key('__lastRetryTime'): + cachedParams['__lastRetryTime'] = timeNow + \ + cachedParams['retryInterval'] + if cachedParams['__lastRetryTime'] > timeNow: + return + # Update retry params + cachedParams['__lastRetryTime'] = timeNow + \ + cachedParams['retryInterval'] + cachedParams['retryCount'] = cachedParams['retryCount'] - 1 + # Re-send request message + try: + self.transportDispatcher.sendMessage( + cachedParams['wholeMsg'], + cachedParams['destTransportDomain'], + cachedParams['destTransportAddress'] + ) + except PySnmpError: + pass + + self.__cacheExpire(retryRequest) + + # XXX + receiveTimerTick = __receiveTimerTick + +if __name__ == '__main__': + from pysnmp.proto import rfc1157, rfc3411 + + class ManagerApplication(AbstractApplication): + def sendReq(self, dsp): + sendPduHandle = dsp.sendPdu( + transportDomain='udp', + transportAddress=('127.0.0.1', 1161), + securityName='mynmsname', + PDU=rfc1157.GetRequestPdu(), + expectResponse=self + ) + + def processResponsePdu(self, dsp, **kwargs): + print self, repr(kwargs) + raise "STOP" + + class AgentApplication(AbstractApplication): + pduTypes = ((rfc1157.Version().get(), rfc1157.GetRequestPdu.tagSet),) + def processPdu(self, dsp, **kwargs): + print self, repr(kwargs) + + pdu = rfc1157.GetResponsePdu() + pdu['request_id'].set(kwargs['PDU']['request_id']) + + # Send response + dsp.returnResponsePdu( + PDU=pdu, + stateReference=kwargs['stateReference'] + ) + + tspDsp = AsynsockDispatcher( + udp=UdpSocketTransport().openClientMode(), + udpd=UdpSocketTransport().openServerMode(('127.0.0.1', 1161)), + ) + + dsp = MsgAndPduDispatcher(transportDispatcher=tspDsp) + + snmpCommunityEntry, = dsp.mibInstrumController.mibBuilder.importSymbols( + 'SNMP-COMMUNITY-MIB', 'snmpCommunityEntry' + ) + dsp.mibInstrumController.writeVars( + (snmpCommunityEntry.getInstNameByIndex(2, 'mynms'), 'mycomm'), + (snmpCommunityEntry.getInstNameByIndex(3, 'mynms'), 'mynmsname'), + # XXX register ContextEngineIds + ) + + dsp.registerContextEngineId(AgentApplication()) + + ManagerApplication().sendReq(dsp) + + try: + dsp.transportDispatcher.runDispatcher() + except "STOP": + dsp.unregisterTransportDispatcher() + +# XXX +# LCD may be used to cache frequently accessed MIB variables +# message version ID <-> MP IDs rewriting (PDU req-id re-write for v1/2 MPM) +# rework cache expiration to index ents to be expired +# rework transport in a loadable fashion diff --git a/pysnmp/proto/secmod/__init__.py b/pysnmp/proto/secmod/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/pysnmp/proto/secmod/__init__.py diff --git a/pysnmp/proto/secmod/base.py b/pysnmp/proto/secmod/base.py new file mode 100644 index 00000000..769b42d4 --- /dev/null +++ b/pysnmp/proto/secmod/base.py @@ -0,0 +1,21 @@ +from pysnmp.proto.secmod import error + +class AbstractSecurityModel: + def __init__(self, mibInstrumController=None): + self.mibInstrumController = mibInstrumController + self.__cacheEntries = {} + + def processIncomingMsg(self, msg, **kwargs): + raise error.BadArgumentError( + 'Security model %s not implemented' % self + ) + + def generateRequestMsg(self, msg, **kwargs): + raise error.BadArgumentError( + 'Security model %s not implemented' % self + ) + + def generateResponseMsg(self, msg, **kwargs): + raise error.BadArgumentError( + 'Security model %s not implemented' % self + ) diff --git a/pysnmp/proto/secmod/rfc2576.py b/pysnmp/proto/secmod/rfc2576.py new file mode 100644 index 00000000..726d87ba --- /dev/null +++ b/pysnmp/proto/secmod/rfc2576.py @@ -0,0 +1,197 @@ +# SNMP v1 & v2c security models implementation +from pysnmp.proto.secmod import base, error +from pysnmp.proto import rfc1157, rfc1905, rfc3411 +from pysnmp.smi.error import NoSuchInstanceError + +__all__ = [ 'SnmpV1SecurityModel', 'SnmpV2cSecurityModel' ] + +class SnmpV1SecurityModel(base.AbstractSecurityModel): + # Map PDU to PDU key names at PDUS choice + _pduMap = { + # SNMP v1 + rfc1157.GetRequestPdu.tagSet: 'get_request', + rfc1157.GetNextRequestPdu.tagSet: 'get_next_request', + rfc1157.GetResponsePdu.tagSet: 'get_response', + rfc1157.SetRequestPdu.tagSet: 'set_request', + rfc1157.TrapPdu.tagSet: 'trap', + } + + _protoMsg = rfc1157.Message + def __init__(self, mibInstrumController=None): + base.AbstractSecurityModel.__init__(self, mibInstrumController) + self.__msg = self._protoMsg() + + # According to rfc2576, community name <-> contextEngineID/contextName + # mapping is up to MP module for notifications but belongs to secmod + # responsibility for other PDU types. Since I do not yet understand + # the reason for such distribution, I moved this code from MP-scope + # in here. + + def generateRequestMsg(self, **kwargs): + # rfc2576: 5.2.3 + snmpCommunityName, \ + snmpCommunitySecurityName, \ + snmpCommunityContextEngineID, \ + snmpCommunityContextName = self.mibInstrumController.mibBuilder.importSymbols( + 'SNMP-COMMUNITY-MIB', + 'snmpCommunityName', + 'snmpCommunitySecurityName', + 'snmpCommunityContextEngineID', + 'snmpCommunityContextName' + ) + mibNodeIdx = snmpCommunitySecurityName + while 1: + try: + mibNodeIdx = snmpCommunitySecurityName.getNextNode( + mibNodeIdx.name + ) + except NoSuchInstanceError: + break + if mibNodeIdx.syntax != kwargs.get('securityName'): + continue + instId = mibNodeIdx.name[len(snmpCommunitySecurityName.name):] + mibNode = snmpCommunityContextEngineID.getNode( + snmpCommunityContextEngineID.name + instId + ) + if mibNode.syntax != kwargs.get('contextEngineID'): + continue + mibNode = snmpCommunityContextName.getNode( + snmpCommunityContextName.name + instId + ) + if mibNode.syntax != kwargs.get('contextName'): + continue + mibNode = snmpCommunityName.getNode( + snmpCommunityName.name + instId + ) + communityName = mibNode.syntax.get() + self.__msg['community'].set(communityName) + transportDomain, transportAddress, pdu = kwargs['scopedPDU'] + self.__msg['pdu'][self._pduMap[pdu.tagSet]] = pdu + return { + 'securityParameters': communityName, + 'wholeMsg': self.__msg.berEncode() + } + raise error.BadArgumentError( + 'Can\'t resolve community name to contextEngineID/Name' + ) + + def generateResponseMsg(self, **kwargs): + # rfc2576: 5.2.2 + securityParameters = kwargs['securityStateReference'] + communityName = securityParameters + self.__msg['community'].set(communityName) + transportDomain, transportAddress, pdu = kwargs['scopedPDU'] + self.__msg['pdu'][self._pduMap[pdu.tagSet]] = pdu + return { + 'securityParameters': securityParameters, + 'wholeMsg': self.__msg.berEncode() + } + + def processIncomingMsg(self, **kwargs): + self.__msg.decodeItem(kwargs['wholeMsg']) + + # rfc2576: 5.2.1 + transportDomain, transportAddress = kwargs.get( + 'securityParameters' + ) + + # According to rfc2576 this should be done at MP but I don't yet see + # the reason why it wouldn't be better done at SM + communityName = self.__msg['community'] + + ( snmpCommunityName, + snmpCommunitySecurityName, + snmpCommunityContextEngineID, + snmpCommunityContextName ) = \ + self.mibInstrumController.mibBuilder.importSymbols( + 'SNMP-COMMUNITY-MIB', + 'snmpCommunityName', + 'snmpCommunitySecurityName', + 'snmpCommunityContextEngineID', + 'snmpCommunityContextName' + ) + mibNodeIdx = snmpCommunityName + while 1: + try: + mibNodeIdx = snmpCommunityName.getNextNode( + mibNodeIdx.name + ) + except NoSuchInstanceError: + break + if mibNodeIdx.syntax != communityName: + continue + break + else: + raise error.BadArgumentError( + 'No matching community name found' + ) + instId = mibNodeIdx.name[len(snmpCommunityName.name):] + communityName = snmpCommunityName.getNode( + snmpCommunityName.name + instId + ) + securityName = snmpCommunitySecurityName.getNode( + snmpCommunitySecurityName.name + instId + ) + contextEngineID = snmpCommunityContextEngineID.getNode( + snmpCommunityContextEngineID.name + instId + ) + contextName = snmpCommunityContextName.getNode( + snmpCommunityContextName.name + instId + ) + snmpEngineID, = self.mibInstrumController.mibBuilder.importSymbols( + 'SNMP-FRAMEWORK-MIB', 'snmpEngineID' + ) + return { + 'securityEngineID': snmpEngineID.syntax.get(), + 'securityName': securityName.syntax.get(), + 'scopedPDU': ( + contextEngineID.syntax.get(), contextName.syntax.get(), + self.__msg['pdu'].values()[0] + ), + 'maxSizeResponseScopedPDU': 65000, # XXX + 'securityStateReference': communityName.syntax.get() + } + +class SnmpV2cSecurityModel(SnmpV1SecurityModel): + _pduMap = { + # SNMP v2c + rfc1905.GetRequestPdu.tagSet: 'get_request', + rfc1905.GetNextRequestPdu.tagSet: 'get_next_request', + rfc1905.GetBulkRequestPdu.tagSet: 'get_bulk_request', + rfc1905.ResponsePdu.tagSet: 'response', + rfc1905.SetRequestPdu.tagSet: 'set_request', + rfc1905.InformRequestPdu.tagSet: 'inform_request', + rfc1905.SnmpV2TrapPdu.tagSet: 'snmpV2_trap', + rfc1905.ReportPdu.tagSet: 'report' + } + _protoMsg = rfc1905.Message + +if __name__ == '__main__': + from pysnmp.proto import rfc1157 + from pysnmp.smi.objects import module + + mib = module.MibModules().loadModules() + + row = mib.getVariable((1,3,6,1,6,3,18,1,1,1)) + mib.writeVars( + (row.getInstNameByIndex(2, 'myrouter'), 'mycomm'), + (row.getInstNameByIndex(3, 'myrouter'), 'myrt'), + ) + + sm = SnmpV1SecurityModel(mib) + smInParams = { + 'scopedPDU': ('', '', rfc1157.GetRequestPdu()), + 'securityName': 'myrt', + 'contextEngineID': '80004fb81c0a80101', + 'contextName': '' + } + + smOutParams = apply(sm.generateRequestMsg, (), smInParams) + print smOutParams + + smInParams = { + 'securityParameters': ('mycomm', '', ''), + 'wholeMsg': smOutParams['wholeMsg'] + } + + print apply(sm.processIncomingMsg, (), smInParams) diff --git a/pysnmp/smi/__init__.py b/pysnmp/smi/__init__.py new file mode 100644 index 00000000..3e6ea1d0 --- /dev/null +++ b/pysnmp/smi/__init__.py @@ -0,0 +1 @@ +"""SNMP SMI""" diff --git a/pysnmp/smi/builder.py b/pysnmp/smi/builder.py new file mode 100644 index 00000000..985a2639 --- /dev/null +++ b/pysnmp/smi/builder.py @@ -0,0 +1,128 @@ +# MIB modules loader +import os +from pysnmp.smi import error +try: + import pysnmp_mibs +except ImportError: + pysnmp_mibs = None + +__all__ = [ 'MibBuilder' ] + +class MibBuilder: + def __init__(self, execContext=None): + self.lastBuildId = 0L + self.execContext = execContext + self.mibSymbols = {} + paths = (os.path.join(os.path.split(error.__file__)[0], 'mibs'),) + if os.environ.has_key('PYSNMPMIBDIR'): + paths = paths + ( + os.path.join(os.path.split(os.environ['PYSNMPMIBDIR'])[0]), + ) + if pysnmp_mibs: + paths = paths + ( + os.path.join(os.path.split(pysnmp_mibs.__file__)[0]), + ) + apply(self.setMibPath, paths) + + # MIB modules management + + def setMibPath(self, *mibPaths): + self.__mibPaths = map(os.path.normpath, mibPaths) + + def getMibPath(self): return tuple(self.__mibPaths) + + def loadModules(self, *modNames): + # Build a list of available modules + if not modNames: + modNames = {} + for mibPath in self.__mibPaths: + try: + for modName in os.listdir(mibPath): + if modName[0] == '_' or modName[-3:] != '.py': + continue + modNames[modName[:-3]] = None + except OSError: + continue + modNames = modNames.keys() + if not modNames: + raise error.SmiError( + 'No MIB module to load at %s' % (self,) + ) + for modName in modNames: + if self.mibSymbols.has_key(modName): + continue + for mibPath in self.__mibPaths: + modPath = os.path.join( + mibPath, modName + '.py' + ) + try: + open(modPath).close() + except IOError, why: + continue + break + else: + raise error.SmiError( + 'MIB module %s open error' % modPath + ) + g = { + 'mibBuilder': self, + 'execContext': self.execContext, + } + + self.mibSymbols[modName] = {} + + try: + execfile(modPath, g) + except StandardError, why: + raise error.SmiError( + 'MIB module %s load error: %s' % (modPath, why) + ) + + self.lastBuildId = self.lastBuildId + 1 + + return self + + def unloadModule(self, *names): + return self + + def importSymbols(self, modName, *symNames): + r = () + for symName in symNames: + if not self.mibSymbols.has_key(modName): + self.loadModules(modName) + if not self.mibSymbols.has_key(modName): + raise error.SmiError( + 'No module %s loaded at %s' % (modName, self) + ) + if not self.mibSymbols[modName].has_key(symName): + raise error.SmiError( + 'No symbol %s::%s at %s' % (modName, symName, self) + ) + r = r + (self.mibSymbols[modName][symName],) + return r + + def exportSymbols(self, modName, **kwargs): + for symName, symObj in kwargs.items(): + if self.mibSymbols[modName].has_key(symName): + raise error.SmiError( + 'Symbol %s already exported at %s' % (symName, modName) + ) + if hasattr(symObj, 'label') and symObj.label: + symName = symObj.label + self.mibSymbols[modName][symName] = symObj + +if __name__ == '__main__': + mibBuilder = MibBuilder().loadModules('Modem-MIB') +# mibBuilder = MibBuilder().loadModules('SNMPv2-SMI') +# mibTree = mibBuilder.importSymbols('SNMPv2-SMI', 'experimental') +# print mibTree + +# get rid of tree MIB structure (index MIB objects by OID name only at MIB +# instrumentation controller) +# implement by-OID indexing at MIB coltroller +# rework MIB instrumentation (tables etc.) to work with +# top-level / plain MIB objects organization +# re-work augmention not to exist at the MibRow level but +# use name lookups instead +# get rid from subtree registration at MIB modules + diff --git a/pysnmp/smi/error.py b/pysnmp/smi/error.py new file mode 100644 index 00000000..939b7f5f --- /dev/null +++ b/pysnmp/smi/error.py @@ -0,0 +1,23 @@ +from pysnmp.error import PySnmpError + +__all__ = [ + 'SmiError', 'NotInitializedError', 'NoSuchInstanceError', + 'InconsistentValueError', 'WrongValueError', + 'NoAccessError', 'ReadOnlyError', 'NotWritableError', + 'NoCreationError', 'RowCreationWanted', 'RowDestructionWanted' + ] + +class SmiError(PySnmpError): pass +class NotInitializedError(SmiError): pass +class NoSuchModuleError(SmiError): pass +class MibVariableError(SmiError): pass +class NoSuchInstanceError(MibVariableError): pass +class InconsistentValueError(MibVariableError): pass +class WrongValueError(MibVariableError): pass +class NoAccessError(MibVariableError): pass +class ReadOnlyError(MibVariableError): pass +class NotWritableError(MibVariableError): pass +class NoCreationError(MibVariableError): pass +# Row management +class RowCreationWanted(MibVariableError): pass +class RowDestructionWanted(MibVariableError): pass diff --git a/pysnmp/smi/indices.py b/pysnmp/smi/indices.py new file mode 100644 index 00000000..bcc493b6 --- /dev/null +++ b/pysnmp/smi/indices.py @@ -0,0 +1,154 @@ +"""Ordered dictionaries classes used for indices""" +from types import DictType, TupleType +from string import join, split, atol +from bisect import bisect + +try: + from sys import version_info +except ImportError: + version_info = ( 0, 0 ) # a really early version + +if version_info < (2, 2): + class OrderedDict: + def __init__(self, **kwargs): + self.__dict = {} + self.__keys = [] + self.__dirty = 0 + self.__sortingFun = cmp + if kwargs: + self.update(kwargs) + self.__dirty = 1 + def __len__(self): return len(self.__dict) + def __getitem__(self, key): return self.__dict[key] + def __setitem__(self, key, value): + if not self.__dict.has_key(key): + self.__keys.append(key) + self.__dict[key] = value + self.__dirty = 1 + def __repr__(self): + if self.__dirty: self.__order() + return repr(self.__dict) + def __str__(self): + if self.__dirty: self.__order() + return str(self.__dict) + def __delitem__(self, key): + if self.__dict.has_key(key): + self.__keys.remove(key) + del self.__dict[key] + self.__dirty = 1 + __delattr__ = __delitem__ + def clear(self): + self.__dict.clear() + self.__keys = [] + self.__dirty = 1 + def get(self, key, default=None): return self.__dict.get(key, default) + def has_key(self, key): return self.__dict.has_key(key) + def keys(self): + if self.__dirty: self.__order() + return list(self.__keys) + def values(self): + if self.__dirty: self.__order() + return map(lambda k, d=self.__dict: d[k], self.__keys) + def items(self): + if self.__dirty: self.__order() + return map(lambda k, d=self.__dict: (k, d[k]), self.__keys) + def update(self, d): + map(lambda (k, v), self=self: self.__setitem__(k, v), d.items()) + def __order(self): + if self.__sortingFun: + self.__keys.sort(self.__sortingFun) + self.__dirty = 0 + def setSortingFun(self, fun): + self.__sortingFun = fun + self.__dirty = 1 + def nextKey(self, key): + keys = self.keys() + if self.has_key(key): + nextIdx = keys.index(key) + 1 + else: + nextIdx = bisect(keys, key) + if nextIdx < len(keys): + return keys[nextIdx] + else: + raise KeyError(key) +else: + class OrderedDict(DictType): + def __init__(self, **kwargs): + self.__keys = [] + self.__dirty = 0 + self.__sortingFun = cmp + super(OrderedDict, self).__init__() + if kwargs: + self.update(kwargs) + def __setitem__(self, key, value): + if not self.has_key(key): + self.__keys.append(key) + super(OrderedDict, self).__setitem__(key, value) + self.__dirty = 1 + def __repr__(self): + if self.__dirty: self.__order() + return super(OrderedDict, self).__repr__() + def __str__(self): + if self.__dirty: self.__order() + return super(OrderedDict, self).__str__() + def __delitem__(self, key): + if super(OrderedDict, self).has_key(key): + self.__keys.remove(key) + super(OrderedDict, self).__delitem__(key) + self.__dirty = 1 + __delattr__ = __delitem__ + def clear(self): + super(OrderedDict, self).clear() + self.__keys = [] + self.__dirty = 1 + def keys(self): + if self.__dirty: self.__order() + return list(self.__keys) + def values(self): + if self.__dirty: self.__order() + return map(lambda k, d=self: d[k], self.__keys) + def items(self): + if self.__dirty: self.__order() + return map(lambda k, d=self: (k, d[k]), self.__keys) + def update(self, d): + map(lambda (k, v), self=self: self.__setitem__(k, v), d.items()) + def __order(self): + if self.__sortingFun: + self.__keys.sort(self.__sortingFun) + self.__dirty = 0 + def setSortingFun(self, fun): + self.__sortingFun = fun + self.__dirty = 1 + def nextKey(self, key): + keys = self.keys() + if self.has_key(key): + nextIdx = keys.index(key) + 1 + else: + nextIdx = bisect(keys, key) + if nextIdx < len(keys): + return keys[nextIdx] + else: + raise KeyError(key) + +class OidOrderedDict(OrderedDict): + def __init__(self, **kwargs): + self.__keysCache = {} + apply(OrderedDict.__init__, [self], kwargs) + self.setSortingFun(lambda o1, o2, self=self: cmp( + self.__keysCache[o1], self.__keysCache[o2])) + + def __setitem__(self, key, value): + if not self.__keysCache.has_key(key): + if type(key) == TupleType: + self.__keysCache[key] = key + else: + self.__keysCache[key] = map( + lambda x: atol(x), filter(None, split(key, '.')) + ) + OrderedDict.__setitem__(self, key, value) + + def __delitem__(self, key): + if self.__keysCache.has_key(key): + del self.__keysCache[key] + OrderedDict.__delitem__(self, key) + __delattr__ = __delitem__ diff --git a/pysnmp/smi/instrum.py b/pysnmp/smi/instrum.py new file mode 100644 index 00000000..c18f3e40 --- /dev/null +++ b/pysnmp/smi/instrum.py @@ -0,0 +1,154 @@ +# MIB modules management +from types import InstanceType +from pysnmp.smi import error + +__all__ = [ 'MibInstrumController' ] + +class MibInstrumController: + fsmReadVar = { + # ( state, status ) -> newState + ('start', 'ok'): 'readTest', + ('readTest', 'ok'): 'readGet', + ('readGet', 'ok'): 'stop', + ('*', 'err'): 'stop' + } + fsmReadNextVar = { + # ( state, status ) -> newState + ('start', 'ok'): 'readTestNext', + ('readTestNext', 'ok'): 'readGetNext', + ('readGetNext', 'ok'): 'stop', + ('*', 'err'): 'stop' + } + fsmWriteVar = { + # ( state, status ) -> newState + ('start', 'ok'): 'writeTest', + ('writeTest', 'ok'): 'writeCommit', + ('writeCommit', 'ok'): 'writeCleanup', + ('writeCleanup', 'ok'): 'readTest', + # Do read after successful write + ('readTest', 'ok'): 'readGet', + ('readGet', 'ok'): 'stop', + # Error handling + ('writeTest', 'err'): 'writeCleanup', + ('writeCommit', 'err'): 'writeUndo', + ('writeUndo', 'ok'): 'readTest', + # Ignore read errors (removed columns) + ('readTest', 'err'): 'stop', + ('readGet', 'err'): 'stop', + ('*', 'err'): 'stop' + } + + def __init__(self, mibBuilder): + self.mibBuilder = mibBuilder + self.lastBuildId = -1 + + # MIB indexing + + def __indexMib(self): + # Build a tree from MIB objects found at currently loaded modules + if self.lastBuildId == self.mibBuilder.lastBuildId: + return + + MibVariable, = self.mibBuilder.importSymbols('SNMPv2-SMI', 'MibVariable') + MibTree, = self.mibBuilder.importSymbols('SNMPv2-SMI', 'MibTree') + MibTableRow, = self.mibBuilder.importSymbols('SNMPv2-SMI', 'MibTableRow') + MibTableColumn, = self.mibBuilder.importSymbols( + 'SNMPv2-SMI', 'MibTableColumn' + ) + + mibTree, = self.mibBuilder.importSymbols('SNMPv2-SMI', 'iso') + + rows = {}; cols = {} + + for mibMod in self.mibBuilder.mibSymbols.values(): + for symObj in mibMod.values(): + if type(symObj) != InstanceType: + continue + if symObj is mibTree: + continue + if not isinstance(symObj, MibTree) and \ + not isinstance(symObj, MibVariable): + continue + if isinstance(symObj, MibTableRow): + rows[symObj.name] = symObj + elif isinstance(symObj, MibTableColumn): + cols[symObj.name] = symObj + else: + mibTree.registerSubtrees(symObj) + + for colName, colObj in cols.items(): + rowName = colObj.name[:-1] + if rows.has_key(rowName): + rows[rowName].registerSubtrees(colObj) + else: + raise error.SmiError( + 'Orphan MIB table column %s at %s' % (colName, self) + ) + for rowObj in rows.values(): + mibTree.registerSubtrees(rowObj) + + self.lastBuildId = self.mibBuilder.lastBuildId + + # MIB instrumentation + + def flipFlopFsm(self, fsmTable, *inputNameVals): + self.__indexMib() + mibTree, = self.mibBuilder.importSymbols('SNMPv2-SMI', 'iso') + outputNameVals = [] + state, status = 'start', 'ok' + myErr = None + while 1: + fsmState = fsmTable.get((state, status)) + if fsmState is None: + fsmState = fsmTable.get(('*', status)) + if fsmState is None: + raise error.SmiError( + 'Unresolved FSM state %s, %s' % (state, status) + ) + state = fsmState + if state == 'stop': + break + for name, val in inputNameVals: + f = getattr(mibTree, state, None) + if f is None: + raise error.SmiError( + 'Unsupported state handler %s at %s' % (state, self) + ) + try: + rval = f(name, val) + except error.MibVariableError, why: + if myErr is None: # Take the first exception + myErr = why + status = 'err' + break + else: + status = 'ok' + if rval is not None: + outputNameVals.append(rval) + if myErr: + raise myErr + return outputNameVals + + def readVars(self, *vars): + return apply(self.flipFlopFsm, (self.fsmReadVar,) + vars) + + def readNextVars(self, *vars): + return apply(self.flipFlopFsm, (self.fsmReadNextVar,) + vars) + + def writeVars(self, *vars): + return apply(self.flipFlopFsm, (self.fsmWriteVar,) + vars) + +if __name__ == '__main__': + from pysnmp.smi.builder import MibBuilder + + mibInstrum = MibInstrumController(MibBuilder().loadModules()) + + print 'Remote manager access to MIB instrumentation (table walk)' + + name, val = (), None + while 1: + try: + name, val = mibInstrum.readNextVars((name, val))[0] + except error.NoSuchInstanceError: + break + print name, val diff --git a/pysnmp/smi/mibs/ASN1.py b/pysnmp/smi/mibs/ASN1.py new file mode 100644 index 00000000..18c4e823 --- /dev/null +++ b/pysnmp/smi/mibs/ASN1.py @@ -0,0 +1,14 @@ +# Base ASN.1 objects + +from pysnmp.asn1 import univ + +Integer = univ.Integer +OctetString = univ.OctetString +BitString = univ.BitString +Null = univ.Null +ObjectIdentifier = univ.ObjectIdentifier + +mibBuilder.exportSymbols( + 'ASN1', Integer=Integer, OctetString=OctetString, + BitString=BitString, Null=Null, ObjectIdentifier=ObjectIdentifier + ) diff --git a/pysnmp/smi/mibs/SNMP-COMMUNITY-MIB.py b/pysnmp/smi/mibs/SNMP-COMMUNITY-MIB.py new file mode 100644 index 00000000..8dfa1302 --- /dev/null +++ b/pysnmp/smi/mibs/SNMP-COMMUNITY-MIB.py @@ -0,0 +1,56 @@ +# PySNMP SMI module. Autogenerated from smidump -f python SNMP-COMMUNITY-MIB +# by libsmi2pysnmp-0.0.3-alpha at Wed Nov 10 13:06:01 2004, +# Python version (2, 2, 1, 'final', 0) + +# Imported just in case new ASN.1 types would be created +from pysnmp.asn1 import subtypes + +# Imports + +( Integer, ObjectIdentifier, OctetString, ) = mibBuilder.importSymbols("ASN1", "Integer", "ObjectIdentifier", "OctetString") +( SnmpAdminString, SnmpEngineID, ) = mibBuilder.importSymbols("SNMP-FRAMEWORK-MIB", "SnmpAdminString", "SnmpEngineID") +( SnmpTagValue, snmpTargetAddrEntry, ) = mibBuilder.importSymbols("SNMP-TARGET-MIB", "SnmpTagValue", "snmpTargetAddrEntry") +( ModuleCompliance, ObjectGroup, ) = mibBuilder.importSymbols("SNMPv2-CONF", "ModuleCompliance", "ObjectGroup") +( Bits, Integer32, Integer32, IpAddress, ModuleIdentity, MibIdentifier, MibVariable, MibTable, MibTableRow, MibTableColumn, TimeTicks, snmpModules, ) = mibBuilder.importSymbols("SNMPv2-SMI", "Bits", "Integer32", "Integer32", "IpAddress", "ModuleIdentity", "MibIdentifier", "MibVariable", "MibTable", "MibTableRow", "MibTableColumn", "TimeTicks", "snmpModules") +( RowStatus, StorageType, ) = mibBuilder.importSymbols("SNMPv2-TC", "RowStatus", "StorageType") + +# Objects + +snmpCommunityMIB = ModuleIdentity((1, 3, 6, 1, 6, 3, 18)) +snmpCommunityMIBObjects = MibIdentifier((1, 3, 6, 1, 6, 3, 18, 1)) +snmpCommunityTable = MibTable((1, 3, 6, 1, 6, 3, 18, 1, 1)) +snmpCommunityEntry = MibTableRow((1, 3, 6, 1, 6, 3, 18, 1, 1, 1)).setIndexNames((1, "SNMP-COMMUNITY-MIB", "snmpCommunityIndex")) +snmpCommunityIndex = MibTableColumn((1, 3, 6, 1, 6, 3, 18, 1, 1, 1, 1)).setColumnInitializer(MibVariable((), SnmpAdminString().addConstraints(subtypes.ValueRangeConstraint(1, 32))).setMaxAccess("noaccess")) +snmpCommunityName = MibTableColumn((1, 3, 6, 1, 6, 3, 18, 1, 1, 1, 2)).setColumnInitializer(MibVariable((), OctetString()).setMaxAccess("readcreate")) +snmpCommunitySecurityName = MibTableColumn((1, 3, 6, 1, 6, 3, 18, 1, 1, 1, 3)).setColumnInitializer(MibVariable((), SnmpAdminString().addConstraints(subtypes.ValueRangeConstraint(1, 32))).setMaxAccess("readcreate")) +snmpCommunityContextEngineID = MibTableColumn((1, 3, 6, 1, 6, 3, 18, 1, 1, 1, 4)).setColumnInitializer(MibVariable((), SnmpEngineID()).setMaxAccess("readcreate")) +snmpCommunityContextName = MibTableColumn((1, 3, 6, 1, 6, 3, 18, 1, 1, 1, 5)).setColumnInitializer(MibVariable((), SnmpAdminString().addConstraints(subtypes.ValueRangeConstraint(0, 32)).set('')).setMaxAccess("readcreate")) +snmpCommunityTransportTag = MibTableColumn((1, 3, 6, 1, 6, 3, 18, 1, 1, 1, 6)).setColumnInitializer(MibVariable((), SnmpTagValue()).setMaxAccess("readcreate")) +snmpCommunityStorageType = MibTableColumn((1, 3, 6, 1, 6, 3, 18, 1, 1, 1, 7)).setColumnInitializer(MibVariable((), StorageType()).setMaxAccess("readcreate")) +snmpCommunityStatus = MibTableColumn((1, 3, 6, 1, 6, 3, 18, 1, 1, 1, 8)).setColumnInitializer(MibVariable((), RowStatus()).setMaxAccess("readcreate")) +snmpTargetAddrExtTable = MibTable((1, 3, 6, 1, 6, 3, 18, 1, 2)) +snmpTargetAddrExtEntry = MibTableRow((1, 3, 6, 1, 6, 3, 18, 1, 2, 1)) +snmpTargetAddrTMask = MibTableColumn((1, 3, 6, 1, 6, 3, 18, 1, 2, 1, 1)).setColumnInitializer(MibVariable((), OctetString().addConstraints(subtypes.ValueRangeConstraint(0, 255)).set('')).setMaxAccess("readcreate")) +snmpTargetAddrMMS = MibTableColumn((1, 3, 6, 1, 6, 3, 18, 1, 2, 1, 2)).setColumnInitializer(MibVariable((), Integer32().addConstraints(subtypes.ValueRangeConstraint(484, 2147483647L)).set(484)).setMaxAccess("readcreate")) +snmpTrapAddress = MibVariable((1, 3, 6, 1, 6, 3, 18, 1, 3), IpAddress()).setMaxAccess("notifyonly") +snmpTrapCommunity = MibVariable((1, 3, 6, 1, 6, 3, 18, 1, 4), OctetString()).setMaxAccess("notifyonly") +snmpCommunityMIBConformance = MibIdentifier((1, 3, 6, 1, 6, 3, 18, 2)) +snmpCommunityMIBCompliances = MibIdentifier((1, 3, 6, 1, 6, 3, 18, 2, 1)) +snmpCommunityMIBGroups = MibIdentifier((1, 3, 6, 1, 6, 3, 18, 2, 2)) + +# Augmentions +snmpTargetAddrEntry, = mibBuilder.importSymbols("SNMP-TARGET-MIB", "snmpTargetAddrEntry") +snmpTargetAddrEntry.registerAugmentions(("SNMP-COMMUNITY-MIB", "snmpTargetAddrExtEntry")) + +# Groups + +snmpProxyTrapForwardGroup = ObjectGroup((1, 3, 6, 1, 6, 3, 18, 2, 2, 3)).setObjects(("SNMP-COMMUNITY-MIB", "snmpTrapAddress"), ("SNMP-COMMUNITY-MIB", "snmpTrapCommunity"), ) +snmpCommunityGroup = ObjectGroup((1, 3, 6, 1, 6, 3, 18, 2, 2, 1)).setObjects(("SNMP-COMMUNITY-MIB", "snmpCommunitySecurityName"), ("SNMP-COMMUNITY-MIB", "snmpCommunityStorageType"), ("SNMP-COMMUNITY-MIB", "snmpCommunityContextName"), ("SNMP-COMMUNITY-MIB", "snmpTargetAddrMMS"), ("SNMP-COMMUNITY-MIB", "snmpTargetAddrTMask"), ("SNMP-COMMUNITY-MIB", "snmpCommunityName"), ("SNMP-COMMUNITY-MIB", "snmpCommunityContextEngineID"), ("SNMP-COMMUNITY-MIB", "snmpCommunityStatus"), ("SNMP-COMMUNITY-MIB", "snmpCommunityTransportTag"), ) + +# Exports + +# Objects +mibBuilder.exportSymbols("SNMP-COMMUNITY-MIB", snmpCommunityMIB=snmpCommunityMIB, snmpCommunityMIBObjects=snmpCommunityMIBObjects, snmpCommunityTable=snmpCommunityTable, snmpCommunityEntry=snmpCommunityEntry, snmpCommunityIndex=snmpCommunityIndex, snmpCommunityName=snmpCommunityName, snmpCommunitySecurityName=snmpCommunitySecurityName, snmpCommunityContextEngineID=snmpCommunityContextEngineID, snmpCommunityContextName=snmpCommunityContextName, snmpCommunityTransportTag=snmpCommunityTransportTag, snmpCommunityStorageType=snmpCommunityStorageType, snmpCommunityStatus=snmpCommunityStatus, snmpTargetAddrExtTable=snmpTargetAddrExtTable, snmpTargetAddrExtEntry=snmpTargetAddrExtEntry, snmpTargetAddrTMask=snmpTargetAddrTMask, snmpTargetAddrMMS=snmpTargetAddrMMS, snmpTrapAddress=snmpTrapAddress, snmpTrapCommunity=snmpTrapCommunity, snmpCommunityMIBConformance=snmpCommunityMIBConformance, snmpCommunityMIBCompliances=snmpCommunityMIBCompliances, snmpCommunityMIBGroups=snmpCommunityMIBGroups) + +# Groups +mibBuilder.exportSymbols("SNMP-COMMUNITY-MIB", snmpProxyTrapForwardGroup=snmpProxyTrapForwardGroup, snmpCommunityGroup=snmpCommunityGroup) diff --git a/pysnmp/smi/mibs/SNMP-FRAMEWORK-MIB.py b/pysnmp/smi/mibs/SNMP-FRAMEWORK-MIB.py new file mode 100644 index 00000000..e71aa719 --- /dev/null +++ b/pysnmp/smi/mibs/SNMP-FRAMEWORK-MIB.py @@ -0,0 +1,106 @@ +from string import join, split +from socket import gethostbyname, gethostname +from pysnmp.asn1 import subtypes + +OctetString, Integer = mibBuilder.importSymbols( + 'ASN1', 'OctetString', 'Integer' + ) +ModuleIdentity, ObjectIdentity, MibIdentifier, \ + MibVariable, snmpModules = mibBuilder.importSymbols( + 'SNMPv2-SMI', 'ModuleIdentity', 'ObjectIdentity', 'MibIdentifier', + 'MibVariable', 'snmpModules' + ) +TextualConvention, = mibBuilder.importSymbols('SNMPv2-TC', 'TextualConvention') + +snmpFrameworkMIB = ModuleIdentity(snmpModules.name + (10,)) + +# TC's + +class SnmpEngineID(TextualConvention, OctetString): + subtypeConstraints = OctetString.subtypeConstraints + ( + subtypes.ValueSizeConstraint(5, 32), + ) + initialValue = '80004fb8' + try: + # Attempt to base engine ID on local IP address + initialValue = initialValue + '1' + join( + map(lambda x: ('%2.2x' % int(x)), + split(gethostbyname(gethostname()), '.')), '' + ) + except: + # ...otherwise, use rudimentary text ID + initialValue = initialValue + '4' + 'mozhinka' + +class SnmpSecurityModel(TextualConvention, Integer): + subtypeConstraints = Integer.subtypeConstraints + ( + subtypes.ValueRangeConstraint(0, 2147483647), + ) + +class SnmpMessageProcessingModel(TextualConvention, Integer): + subtypeConstraints = Integer.subtypeConstraints + ( + subtypes.ValueRangeConstraint(0, 2147483647), + ) + +class SnmpSecurityLevel(TextualConvention, Integer): + subtypeConstraints = Integer.subtypeConstraints + ( + subtypes.SingleValueConstraint(1, 2, 3), + ) + namedValues = Integer.namedValues.clone( + ('noAuthNoPriv', 1), ('authNoPriv', 2), ('authPriv', 3) + ) + initialValue = 1 + +class SnmpAdminString(TextualConvention, OctetString): + subtypeConstraints = OctetString.subtypeConstraints + ( + subtypes.ValueSizeConstraint(0, 255), + ) + displayHint = "255a" + +snmpFrameworkAdmin = MibIdentifier(snmpFrameworkMIB.name + (1,)) +snmpFrameworkMIBObjects = MibIdentifier(snmpFrameworkMIB.name + (2,)) +snmpFrameworkMIBConformance = MibIdentifier(snmpFrameworkMIB.name + (3,)) + +snmpEngine = MibIdentifier(snmpFrameworkMIBObjects.name + (1,)) + +# MIB objects + +snmpEngineID = MibVariable(snmpEngine.name + (1,), SnmpEngineID()) +snmpEngineBoots = MibVariable( + snmpEngine.name + (2,), Integer().addConstraints( + subtypes.ValueRangeConstraint(0, 2147483647) + ) + ) +snmpEngineTime = MibVariable( + snmpEngine.name + (3,), Integer().addConstraints( + subtypes.ValueRangeConstraint(0, 2147483647) + ) + ) +snmpEngineMaxMessageSize = MibVariable( + snmpEngine.name + (4,), Integer().addConstraints( + subtypes.ValueRangeConstraint(484, 2147483647) + ) + ) + +# OI's +snmpAuthProtocols = ObjectIdentity(snmpFrameworkAdmin.name + (1,)) +snmpPrivProtocols = ObjectIdentity(snmpFrameworkAdmin.name + (2,)) + +mibBuilder.exportSymbols( + 'SNMP-FRAMEWORK-MIB', + snmpFrameworkMIB=snmpFrameworkMIB, + SnmpEngineID=SnmpEngineID, + SnmpSecurityModel=SnmpSecurityModel, + SnmpMessageProcessingModel=SnmpMessageProcessingModel, + SnmpSecurityLevel=SnmpSecurityLevel, + SnmpAdminString=SnmpAdminString, + snmpFrameworkAdmin=snmpFrameworkAdmin, + snmpFrameworkMIBObjects=snmpFrameworkMIBObjects, + snmpFrameworkMIBConformance=snmpFrameworkMIBConformance, + snmpEngine=snmpEngine, + snmpEngineID=snmpEngineID, + snmpEngineBoots=snmpEngineBoots, + snmpEngineTime=snmpEngineTime, + snmpEngineMaxMessageSize=snmpEngineMaxMessageSize, + snmpAuthProtocols=snmpAuthProtocols, + snmpPrivProtocols=snmpPrivProtocols + ) diff --git a/pysnmp/smi/mibs/SNMP-MPD-MIB.py b/pysnmp/smi/mibs/SNMP-MPD-MIB.py new file mode 100644 index 00000000..5dd43fc6 --- /dev/null +++ b/pysnmp/smi/mibs/SNMP-MPD-MIB.py @@ -0,0 +1,39 @@ +# PySNMP SMI module. Autogenerated from smidump -f python SNMP-MPD-MIB +# by libsmi2pysnmp-0.0.3-alpha at Wed Nov 10 13:10:15 2004, +# Python version (2, 2, 1, 'final', 0) + +# Imported just in case new ASN.1 types would be created +from pysnmp.asn1 import subtypes + +# Imports + +( Integer, ObjectIdentifier, OctetString, ) = mibBuilder.importSymbols("ASN1", "Integer", "ObjectIdentifier", "OctetString") +( ModuleCompliance, ObjectGroup, ) = mibBuilder.importSymbols("SNMPv2-CONF", "ModuleCompliance", "ObjectGroup") +( Bits, Counter32, Integer32, ModuleIdentity, MibIdentifier, MibVariable, MibTable, MibTableRow, MibTableColumn, TimeTicks, snmpModules, ) = mibBuilder.importSymbols("SNMPv2-SMI", "Bits", "Counter32", "Integer32", "ModuleIdentity", "MibIdentifier", "MibVariable", "MibTable", "MibTableRow", "MibTableColumn", "TimeTicks", "snmpModules") + +# Objects + +snmpMPDMIB = ModuleIdentity((1, 3, 6, 1, 6, 3, 11)) +snmpMPDAdmin = MibIdentifier((1, 3, 6, 1, 6, 3, 11, 1)) +snmpMPDMIBObjects = MibIdentifier((1, 3, 6, 1, 6, 3, 11, 2)) +snmpMPDStats = MibIdentifier((1, 3, 6, 1, 6, 3, 11, 2, 1)) +snmpUnknownSecurityModels = MibVariable((1, 3, 6, 1, 6, 3, 11, 2, 1, 1), Counter32()).setMaxAccess("readonly") +snmpInvalidMsgs = MibVariable((1, 3, 6, 1, 6, 3, 11, 2, 1, 2), Counter32()).setMaxAccess("readonly") +snmpUnknownPDUHandlers = MibVariable((1, 3, 6, 1, 6, 3, 11, 2, 1, 3), Counter32()).setMaxAccess("readonly") +snmpMPDMIBConformance = MibIdentifier((1, 3, 6, 1, 6, 3, 11, 3)) +snmpMPDMIBCompliances = MibIdentifier((1, 3, 6, 1, 6, 3, 11, 3, 1)) +snmpMPDMIBGroups = MibIdentifier((1, 3, 6, 1, 6, 3, 11, 3, 2)) + +# Augmentions + +# Groups + +snmpMPDGroup = ObjectGroup((1, 3, 6, 1, 6, 3, 11, 3, 2, 1)).setObjects(("SNMP-MPD-MIB", "snmpInvalidMsgs"), ("SNMP-MPD-MIB", "snmpUnknownPDUHandlers"), ("SNMP-MPD-MIB", "snmpUnknownSecurityModels"), ) + +# Exports + +# Objects +mibBuilder.exportSymbols("SNMP-MPD-MIB", snmpMPDMIB=snmpMPDMIB, snmpMPDAdmin=snmpMPDAdmin, snmpMPDMIBObjects=snmpMPDMIBObjects, snmpMPDStats=snmpMPDStats, snmpUnknownSecurityModels=snmpUnknownSecurityModels, snmpInvalidMsgs=snmpInvalidMsgs, snmpUnknownPDUHandlers=snmpUnknownPDUHandlers, snmpMPDMIBConformance=snmpMPDMIBConformance, snmpMPDMIBCompliances=snmpMPDMIBCompliances, snmpMPDMIBGroups=snmpMPDMIBGroups) + +# Groups +mibBuilder.exportSymbols("SNMP-MPD-MIB", snmpMPDGroup=snmpMPDGroup) diff --git a/pysnmp/smi/mibs/SNMP-NOTIFICATION-MIB.py b/pysnmp/smi/mibs/SNMP-NOTIFICATION-MIB.py new file mode 100644 index 00000000..3a9c7153 --- /dev/null +++ b/pysnmp/smi/mibs/SNMP-NOTIFICATION-MIB.py @@ -0,0 +1,57 @@ +# PySNMP SMI module. Autogenerated from smidump -f python SNMP-NOTIFICATION-MIB +# by libsmi2pysnmp-0.0.3-alpha at Wed Nov 10 13:10:42 2004, +# Python version (2, 2, 1, 'final', 0) + +# Imported just in case new ASN.1 types would be created +from pysnmp.asn1 import subtypes + +# Imports + +( Integer, ObjectIdentifier, OctetString, ) = mibBuilder.importSymbols("ASN1", "Integer", "ObjectIdentifier", "OctetString") +( SnmpAdminString, ) = mibBuilder.importSymbols("SNMP-FRAMEWORK-MIB", "SnmpAdminString") +( SnmpTagValue, snmpTargetBasicGroup, snmpTargetBasicGroup, snmpTargetBasicGroup, snmpTargetParamsMPModel, snmpTargetParamsName, snmpTargetParamsRowStatus, snmpTargetParamsSecurityLevel, snmpTargetParamsSecurityModel, snmpTargetParamsSecurityName, snmpTargetParamsStorageType, snmpTargetResponseGroup, ) = mibBuilder.importSymbols("SNMP-TARGET-MIB", "SnmpTagValue", "snmpTargetBasicGroup", "snmpTargetBasicGroup", "snmpTargetBasicGroup", "snmpTargetParamsMPModel", "snmpTargetParamsName", "snmpTargetParamsRowStatus", "snmpTargetParamsSecurityLevel", "snmpTargetParamsSecurityModel", "snmpTargetParamsSecurityName", "snmpTargetParamsStorageType", "snmpTargetResponseGroup") +( ModuleCompliance, ObjectGroup, ) = mibBuilder.importSymbols("SNMPv2-CONF", "ModuleCompliance", "ObjectGroup") +( Bits, Integer32, ModuleIdentity, MibIdentifier, MibVariable, MibTable, MibTableRow, MibTableColumn, TimeTicks, snmpModules, ) = mibBuilder.importSymbols("SNMPv2-SMI", "Bits", "Integer32", "ModuleIdentity", "MibIdentifier", "MibVariable", "MibTable", "MibTableRow", "MibTableColumn", "TimeTicks", "snmpModules") +( RowStatus, StorageType, ) = mibBuilder.importSymbols("SNMPv2-TC", "RowStatus", "StorageType") + +# Objects + +snmpNotificationMIB = ModuleIdentity((1, 3, 6, 1, 6, 3, 13)) +snmpNotifyObjects = MibIdentifier((1, 3, 6, 1, 6, 3, 13, 1)) +snmpNotifyTable = MibTable((1, 3, 6, 1, 6, 3, 13, 1, 1)) +snmpNotifyEntry = MibTableRow((1, 3, 6, 1, 6, 3, 13, 1, 1, 1)).setIndexNames((1, "SNMP-NOTIFICATION-MIB", "snmpNotifyName")) +snmpNotifyName = MibTableColumn((1, 3, 6, 1, 6, 3, 13, 1, 1, 1, 1)).setColumnInitializer(MibVariable((), SnmpAdminString().addConstraints(subtypes.ValueRangeConstraint(1, 32))).setMaxAccess("noaccess")) +snmpNotifyTag = MibTableColumn((1, 3, 6, 1, 6, 3, 13, 1, 1, 1, 2)).setColumnInitializer(MibVariable((), SnmpTagValue()).setMaxAccess("readcreate")) +snmpNotifyType = MibTableColumn((1, 3, 6, 1, 6, 3, 13, 1, 1, 1, 3)).setColumnInitializer(MibVariable((), Integer().addConstraints(subtypes.SingleValueConstraint(2,1,)).addNamedValues(("trap", 1), ("inform", 2), ).set(1)).setMaxAccess("readcreate")) +snmpNotifyStorageType = MibTableColumn((1, 3, 6, 1, 6, 3, 13, 1, 1, 1, 4)).setColumnInitializer(MibVariable((), StorageType()).setMaxAccess("readcreate")) +snmpNotifyRowStatus = MibTableColumn((1, 3, 6, 1, 6, 3, 13, 1, 1, 1, 5)).setColumnInitializer(MibVariable((), RowStatus()).setMaxAccess("readcreate")) +snmpNotifyFilterProfileTable = MibTable((1, 3, 6, 1, 6, 3, 13, 1, 2)) +snmpNotifyFilterProfileEntry = MibTableRow((1, 3, 6, 1, 6, 3, 13, 1, 2, 1)).setIndexNames((1, "SNMP-TARGET-MIB", "snmpTargetParamsName")) +snmpNotifyFilterProfileName = MibTableColumn((1, 3, 6, 1, 6, 3, 13, 1, 2, 1, 1)).setColumnInitializer(MibVariable((), SnmpAdminString().addConstraints(subtypes.ValueRangeConstraint(1, 32))).setMaxAccess("readcreate")) +snmpNotifyFilterProfileStorType = MibTableColumn((1, 3, 6, 1, 6, 3, 13, 1, 2, 1, 2)).setColumnInitializer(MibVariable((), StorageType()).setMaxAccess("readcreate")) +snmpNotifyFilterProfileRowStatus = MibTableColumn((1, 3, 6, 1, 6, 3, 13, 1, 2, 1, 3)).setColumnInitializer(MibVariable((), RowStatus()).setMaxAccess("readcreate")) +snmpNotifyFilterTable = MibTable((1, 3, 6, 1, 6, 3, 13, 1, 3)) +snmpNotifyFilterEntry = MibTableRow((1, 3, 6, 1, 6, 3, 13, 1, 3, 1)).setIndexNames((0, "SNMP-NOTIFICATION-MIB", "snmpNotifyFilterProfileName"), (1, "SNMP-NOTIFICATION-MIB", "snmpNotifyFilterSubtree")) +snmpNotifyFilterSubtree = MibTableColumn((1, 3, 6, 1, 6, 3, 13, 1, 3, 1, 1)).setColumnInitializer(MibVariable((), ObjectIdentifier()).setMaxAccess("noaccess")) +snmpNotifyFilterMask = MibTableColumn((1, 3, 6, 1, 6, 3, 13, 1, 3, 1, 2)).setColumnInitializer(MibVariable((), OctetString().addConstraints(subtypes.ValueRangeConstraint(0, 16)).set('')).setMaxAccess("readcreate")) +snmpNotifyFilterType = MibTableColumn((1, 3, 6, 1, 6, 3, 13, 1, 3, 1, 3)).setColumnInitializer(MibVariable((), Integer().addConstraints(subtypes.SingleValueConstraint(1,2,)).addNamedValues(("included", 1), ("excluded", 2), ).set(1)).setMaxAccess("readcreate")) +snmpNotifyFilterStorageType = MibTableColumn((1, 3, 6, 1, 6, 3, 13, 1, 3, 1, 4)).setColumnInitializer(MibVariable((), StorageType()).setMaxAccess("readcreate")) +snmpNotifyFilterRowStatus = MibTableColumn((1, 3, 6, 1, 6, 3, 13, 1, 3, 1, 5)).setColumnInitializer(MibVariable((), RowStatus()).setMaxAccess("readcreate")) +snmpNotifyConformance = MibIdentifier((1, 3, 6, 1, 6, 3, 13, 3)) +snmpNotifyCompliances = MibIdentifier((1, 3, 6, 1, 6, 3, 13, 3, 1)) +snmpNotifyGroups = MibIdentifier((1, 3, 6, 1, 6, 3, 13, 3, 2)) + +# Augmentions + +# Groups + +snmpNotifyFilterGroup = ObjectGroup((1, 3, 6, 1, 6, 3, 13, 3, 2, 2)).setObjects(("SNMP-NOTIFICATION-MIB", "snmpNotifyFilterRowStatus"), ("SNMP-NOTIFICATION-MIB", "snmpNotifyFilterProfileStorType"), ("SNMP-NOTIFICATION-MIB", "snmpNotifyFilterStorageType"), ("SNMP-NOTIFICATION-MIB", "snmpNotifyFilterProfileName"), ("SNMP-NOTIFICATION-MIB", "snmpNotifyFilterMask"), ("SNMP-NOTIFICATION-MIB", "snmpNotifyFilterType"), ("SNMP-NOTIFICATION-MIB", "snmpNotifyFilterProfileRowStatus"), ) +snmpNotifyGroup = ObjectGroup((1, 3, 6, 1, 6, 3, 13, 3, 2, 1)).setObjects(("SNMP-NOTIFICATION-MIB", "snmpNotifyTag"), ("SNMP-NOTIFICATION-MIB", "snmpNotifyRowStatus"), ("SNMP-NOTIFICATION-MIB", "snmpNotifyStorageType"), ("SNMP-NOTIFICATION-MIB", "snmpNotifyType"), ) + +# Exports + +# Objects +mibBuilder.exportSymbols("SNMP-NOTIFICATION-MIB", snmpNotificationMIB=snmpNotificationMIB, snmpNotifyObjects=snmpNotifyObjects, snmpNotifyTable=snmpNotifyTable, snmpNotifyEntry=snmpNotifyEntry, snmpNotifyName=snmpNotifyName, snmpNotifyTag=snmpNotifyTag, snmpNotifyType=snmpNotifyType, snmpNotifyStorageType=snmpNotifyStorageType, snmpNotifyRowStatus=snmpNotifyRowStatus, snmpNotifyFilterProfileTable=snmpNotifyFilterProfileTable, snmpNotifyFilterProfileEntry=snmpNotifyFilterProfileEntry, snmpNotifyFilterProfileName=snmpNotifyFilterProfileName, snmpNotifyFilterProfileStorType=snmpNotifyFilterProfileStorType, snmpNotifyFilterProfileRowStatus=snmpNotifyFilterProfileRowStatus, snmpNotifyFilterTable=snmpNotifyFilterTable, snmpNotifyFilterEntry=snmpNotifyFilterEntry, snmpNotifyFilterSubtree=snmpNotifyFilterSubtree, snmpNotifyFilterMask=snmpNotifyFilterMask, snmpNotifyFilterType=snmpNotifyFilterType, snmpNotifyFilterStorageType=snmpNotifyFilterStorageType, snmpNotifyFilterRowStatus=snmpNotifyFilterRowStatus, snmpNotifyConformance=snmpNotifyConformance, snmpNotifyCompliances=snmpNotifyCompliances, snmpNotifyGroups=snmpNotifyGroups) + +# Groups +mibBuilder.exportSymbols("SNMP-NOTIFICATION-MIB", snmpNotifyFilterGroup=snmpNotifyFilterGroup, snmpNotifyGroup=snmpNotifyGroup) diff --git a/pysnmp/smi/mibs/SNMP-TARGET-MIB.py b/pysnmp/smi/mibs/SNMP-TARGET-MIB.py new file mode 100644 index 00000000..35426cd9 --- /dev/null +++ b/pysnmp/smi/mibs/SNMP-TARGET-MIB.py @@ -0,0 +1,75 @@ +# PySNMP SMI module. Autogenerated from smidump -f python SNMP-TARGET-MIB +# by libsmi2pysnmp-0.0.3-alpha at Wed Nov 10 13:11:24 2004, +# Python version (2, 2, 1, 'final', 0) + +# Imported just in case new ASN.1 types would be created +from pysnmp.asn1 import subtypes + +# Imports + +( Integer, ObjectIdentifier, OctetString, ) = mibBuilder.importSymbols("ASN1", "Integer", "ObjectIdentifier", "OctetString") +( SnmpAdminString, SnmpMessageProcessingModel, SnmpSecurityLevel, SnmpSecurityModel, ) = mibBuilder.importSymbols("SNMP-FRAMEWORK-MIB", "SnmpAdminString", "SnmpMessageProcessingModel", "SnmpSecurityLevel", "SnmpSecurityModel") +( ModuleCompliance, ObjectGroup, ) = mibBuilder.importSymbols("SNMPv2-CONF", "ModuleCompliance", "ObjectGroup") +( Bits, Counter32, Integer32, Integer32, ModuleIdentity, MibIdentifier, MibVariable, MibTable, MibTableRow, MibTableColumn, TimeTicks, snmpModules, ) = mibBuilder.importSymbols("SNMPv2-SMI", "Bits", "Counter32", "Integer32", "Integer32", "ModuleIdentity", "MibIdentifier", "MibVariable", "MibTable", "MibTableRow", "MibTableColumn", "TimeTicks", "snmpModules") +( RowStatus, StorageType, TAddress, TDomain, TextualConvention, TestAndIncr, TimeInterval, ) = mibBuilder.importSymbols("SNMPv2-TC", "RowStatus", "StorageType", "TAddress", "TDomain", "TextualConvention", "TestAndIncr", "TimeInterval") + +# Types + +class SnmpTagList(TextualConvention, OctetString): + subtypeConstraints = OctetString.subtypeConstraints + ( subtypes.ValueRangeConstraint(0, 255), ) + pass + +class SnmpTagValue(TextualConvention, OctetString): + subtypeConstraints = OctetString.subtypeConstraints + ( subtypes.ValueRangeConstraint(0, 255), ) + pass + + +# Objects + +snmpTargetMIB = ModuleIdentity((1, 3, 6, 1, 6, 3, 12)) +snmpTargetObjects = MibIdentifier((1, 3, 6, 1, 6, 3, 12, 1)) +snmpTargetSpinLock = MibVariable((1, 3, 6, 1, 6, 3, 12, 1, 1), TestAndIncr()).setMaxAccess("readcreate") +snmpTargetAddrTable = MibTable((1, 3, 6, 1, 6, 3, 12, 1, 2)) +snmpTargetAddrEntry = MibTableRow((1, 3, 6, 1, 6, 3, 12, 1, 2, 1)).setIndexNames((1, "SNMP-TARGET-MIB", "snmpTargetAddrName")) +snmpTargetAddrName = MibTableColumn((1, 3, 6, 1, 6, 3, 12, 1, 2, 1, 1)).setColumnInitializer(MibVariable((), SnmpAdminString().addConstraints(subtypes.ValueRangeConstraint(1, 32))).setMaxAccess("noaccess")) +snmpTargetAddrTDomain = MibTableColumn((1, 3, 6, 1, 6, 3, 12, 1, 2, 1, 2)).setColumnInitializer(MibVariable((), TDomain()).setMaxAccess("readcreate")) +snmpTargetAddrTAddress = MibTableColumn((1, 3, 6, 1, 6, 3, 12, 1, 2, 1, 3)).setColumnInitializer(MibVariable((), TAddress()).setMaxAccess("readcreate")) +snmpTargetAddrTimeout = MibTableColumn((1, 3, 6, 1, 6, 3, 12, 1, 2, 1, 4)).setColumnInitializer(MibVariable((), TimeInterval()).setMaxAccess("readcreate")) +snmpTargetAddrRetryCount = MibTableColumn((1, 3, 6, 1, 6, 3, 12, 1, 2, 1, 5)).setColumnInitializer(MibVariable((), Integer32().addConstraints(subtypes.ValueRangeConstraint(0, 255)).set(3)).setMaxAccess("readcreate")) +snmpTargetAddrTagList = MibTableColumn((1, 3, 6, 1, 6, 3, 12, 1, 2, 1, 6)).setColumnInitializer(MibVariable((), SnmpTagList()).setMaxAccess("readcreate")) +snmpTargetAddrParams = MibTableColumn((1, 3, 6, 1, 6, 3, 12, 1, 2, 1, 7)).setColumnInitializer(MibVariable((), SnmpAdminString().addConstraints(subtypes.ValueRangeConstraint(1, 32))).setMaxAccess("readcreate")) +snmpTargetAddrStorageType = MibTableColumn((1, 3, 6, 1, 6, 3, 12, 1, 2, 1, 8)).setColumnInitializer(MibVariable((), StorageType()).setMaxAccess("readcreate")) +snmpTargetAddrRowStatus = MibTableColumn((1, 3, 6, 1, 6, 3, 12, 1, 2, 1, 9)).setColumnInitializer(MibVariable((), RowStatus()).setMaxAccess("readcreate")) +snmpTargetParamsTable = MibTable((1, 3, 6, 1, 6, 3, 12, 1, 3)) +snmpTargetParamsEntry = MibTableRow((1, 3, 6, 1, 6, 3, 12, 1, 3, 1)).setIndexNames((1, "SNMP-TARGET-MIB", "snmpTargetParamsName")) +snmpTargetParamsName = MibTableColumn((1, 3, 6, 1, 6, 3, 12, 1, 3, 1, 1)).setColumnInitializer(MibVariable((), SnmpAdminString().addConstraints(subtypes.ValueRangeConstraint(1, 32))).setMaxAccess("noaccess")) +snmpTargetParamsMPModel = MibTableColumn((1, 3, 6, 1, 6, 3, 12, 1, 3, 1, 2)).setColumnInitializer(MibVariable((), SnmpMessageProcessingModel()).setMaxAccess("readcreate")) +snmpTargetParamsSecurityModel = MibTableColumn((1, 3, 6, 1, 6, 3, 12, 1, 3, 1, 3)).setColumnInitializer(MibVariable((), SnmpSecurityModel().addConstraints(subtypes.ValueRangeConstraint(1, 2147483647L))).setMaxAccess("readcreate")) +snmpTargetParamsSecurityName = MibTableColumn((1, 3, 6, 1, 6, 3, 12, 1, 3, 1, 4)).setColumnInitializer(MibVariable((), SnmpAdminString()).setMaxAccess("readcreate")) +snmpTargetParamsSecurityLevel = MibTableColumn((1, 3, 6, 1, 6, 3, 12, 1, 3, 1, 5)).setColumnInitializer(MibVariable((), SnmpSecurityLevel()).setMaxAccess("readcreate")) +snmpTargetParamsStorageType = MibTableColumn((1, 3, 6, 1, 6, 3, 12, 1, 3, 1, 6)).setColumnInitializer(MibVariable((), StorageType()).setMaxAccess("readcreate")) +snmpTargetParamsRowStatus = MibTableColumn((1, 3, 6, 1, 6, 3, 12, 1, 3, 1, 7)).setColumnInitializer(MibVariable((), RowStatus()).setMaxAccess("readcreate")) +snmpUnavailableContexts = MibVariable((1, 3, 6, 1, 6, 3, 12, 1, 4), Counter32()).setMaxAccess("readonly") +snmpUnknownContexts = MibVariable((1, 3, 6, 1, 6, 3, 12, 1, 5), Counter32()).setMaxAccess("readonly") +snmpTargetConformance = MibIdentifier((1, 3, 6, 1, 6, 3, 12, 3)) +snmpTargetCompliances = MibIdentifier((1, 3, 6, 1, 6, 3, 12, 3, 1)) +snmpTargetGroups = MibIdentifier((1, 3, 6, 1, 6, 3, 12, 3, 2)) + +# Augmentions + +# Groups + +snmpTargetResponseGroup = ObjectGroup((1, 3, 6, 1, 6, 3, 12, 3, 2, 2)).setObjects(("SNMP-TARGET-MIB", "snmpTargetAddrRetryCount"), ("SNMP-TARGET-MIB", "snmpTargetAddrTimeout"), ) +snmpTargetCommandResponderGroup = ObjectGroup((1, 3, 6, 1, 6, 3, 12, 3, 2, 3)).setObjects(("SNMP-TARGET-MIB", "snmpUnavailableContexts"), ("SNMP-TARGET-MIB", "snmpUnknownContexts"), ) +snmpTargetBasicGroup = ObjectGroup((1, 3, 6, 1, 6, 3, 12, 3, 2, 1)).setObjects(("SNMP-TARGET-MIB", "snmpTargetAddrTDomain"), ("SNMP-TARGET-MIB", "snmpTargetAddrStorageType"), ("SNMP-TARGET-MIB", "snmpTargetParamsRowStatus"), ("SNMP-TARGET-MIB", "snmpTargetParamsMPModel"), ("SNMP-TARGET-MIB", "snmpTargetAddrParams"), ("SNMP-TARGET-MIB", "snmpTargetParamsSecurityName"), ("SNMP-TARGET-MIB", "snmpTargetAddrRowStatus"), ("SNMP-TARGET-MIB", "snmpTargetAddrTAddress"), ("SNMP-TARGET-MIB", "snmpTargetParamsStorageType"), ("SNMP-TARGET-MIB", "snmpTargetAddrTagList"), ("SNMP-TARGET-MIB", "snmpTargetSpinLock"), ("SNMP-TARGET-MIB", "snmpTargetParamsSecurityLevel"), ("SNMP-TARGET-MIB", "snmpTargetParamsSecurityModel"), ) + +# Exports + +# Types +mibBuilder.exportSymbols("SNMP-TARGET-MIB", SnmpTagList=SnmpTagList, SnmpTagValue=SnmpTagValue) + +# Objects +mibBuilder.exportSymbols("SNMP-TARGET-MIB", snmpTargetMIB=snmpTargetMIB, snmpTargetObjects=snmpTargetObjects, snmpTargetSpinLock=snmpTargetSpinLock, snmpTargetAddrTable=snmpTargetAddrTable, snmpTargetAddrEntry=snmpTargetAddrEntry, snmpTargetAddrName=snmpTargetAddrName, snmpTargetAddrTDomain=snmpTargetAddrTDomain, snmpTargetAddrTAddress=snmpTargetAddrTAddress, snmpTargetAddrTimeout=snmpTargetAddrTimeout, snmpTargetAddrRetryCount=snmpTargetAddrRetryCount, snmpTargetAddrTagList=snmpTargetAddrTagList, snmpTargetAddrParams=snmpTargetAddrParams, snmpTargetAddrStorageType=snmpTargetAddrStorageType, snmpTargetAddrRowStatus=snmpTargetAddrRowStatus, snmpTargetParamsTable=snmpTargetParamsTable, snmpTargetParamsEntry=snmpTargetParamsEntry, snmpTargetParamsName=snmpTargetParamsName, snmpTargetParamsMPModel=snmpTargetParamsMPModel, snmpTargetParamsSecurityModel=snmpTargetParamsSecurityModel, snmpTargetParamsSecurityName=snmpTargetParamsSecurityName, snmpTargetParamsSecurityLevel=snmpTargetParamsSecurityLevel, snmpTargetParamsStorageType=snmpTargetParamsStorageType, snmpTargetParamsRowStatus=snmpTargetParamsRowStatus, snmpUnavailableContexts=snmpUnavailableContexts, snmpUnknownContexts=snmpUnknownContexts, snmpTargetConformance=snmpTargetConformance, snmpTargetCompliances=snmpTargetCompliances, snmpTargetGroups=snmpTargetGroups) + +# Groups +mibBuilder.exportSymbols("SNMP-TARGET-MIB", snmpTargetResponseGroup=snmpTargetResponseGroup, snmpTargetCommandResponderGroup=snmpTargetCommandResponderGroup, snmpTargetBasicGroup=snmpTargetBasicGroup) diff --git a/pysnmp/smi/mibs/SNMP-USER-BASED-SM-MIB.py b/pysnmp/smi/mibs/SNMP-USER-BASED-SM-MIB.py new file mode 100644 index 00000000..7b0e9ebf --- /dev/null +++ b/pysnmp/smi/mibs/SNMP-USER-BASED-SM-MIB.py @@ -0,0 +1,74 @@ +# PySNMP SMI module. Autogenerated from smidump -f python SNMP-USER-BASED-SM-MIB +# by libsmi2pysnmp-0.0.3-alpha at Wed Nov 10 13:12:09 2004, +# Python version (2, 2, 1, 'final', 0) + +# Imported just in case new ASN.1 types would be created +from pysnmp.asn1 import subtypes + +# Imports + +( Integer, ObjectIdentifier, OctetString, ) = mibBuilder.importSymbols("ASN1", "Integer", "ObjectIdentifier", "OctetString") +( SnmpAdminString, SnmpEngineID, snmpAuthProtocols, snmpPrivProtocols, ) = mibBuilder.importSymbols("SNMP-FRAMEWORK-MIB", "SnmpAdminString", "SnmpEngineID", "snmpAuthProtocols", "snmpPrivProtocols") +( ModuleCompliance, ObjectGroup, ) = mibBuilder.importSymbols("SNMPv2-CONF", "ModuleCompliance", "ObjectGroup") +( Bits, Counter32, Integer32, ModuleIdentity, MibIdentifier, ObjectIdentity, MibVariable, MibTable, MibTableRow, MibTableColumn, TimeTicks, snmpModules, ) = mibBuilder.importSymbols("SNMPv2-SMI", "Bits", "Counter32", "Integer32", "ModuleIdentity", "MibIdentifier", "ObjectIdentity", "MibVariable", "MibTable", "MibTableRow", "MibTableColumn", "TimeTicks", "snmpModules") +( AutonomousType, RowPointer, RowStatus, StorageType, TextualConvention, TestAndIncr, ) = mibBuilder.importSymbols("SNMPv2-TC", "AutonomousType", "RowPointer", "RowStatus", "StorageType", "TextualConvention", "TestAndIncr") + +# Types + +class KeyChange(OctetString): + pass + + +# Objects + +usmNoAuthProtocol = MibIdentifier((1, 3, 6, 1, 6, 3, 10, 1, 1, 1)) +usmHMACMD5AuthProtocol = MibIdentifier((1, 3, 6, 1, 6, 3, 10, 1, 1, 2)) +usmHMACSHAAuthProtocol = MibIdentifier((1, 3, 6, 1, 6, 3, 10, 1, 1, 3)) +usmNoPrivProtocol = MibIdentifier((1, 3, 6, 1, 6, 3, 10, 1, 2, 1)) +usmDESPrivProtocol = MibIdentifier((1, 3, 6, 1, 6, 3, 10, 1, 2, 2)) +snmpUsmMIB = ModuleIdentity((1, 3, 6, 1, 6, 3, 15)) +usmMIBObjects = MibIdentifier((1, 3, 6, 1, 6, 3, 15, 1)) +usmStats = MibIdentifier((1, 3, 6, 1, 6, 3, 15, 1, 1)) +usmStatsUnsupportedSecLevels = MibVariable((1, 3, 6, 1, 6, 3, 15, 1, 1, 1), Counter32()).setMaxAccess("readonly") +usmStatsNotInTimeWindows = MibVariable((1, 3, 6, 1, 6, 3, 15, 1, 1, 2), Counter32()).setMaxAccess("readonly") +usmStatsUnknownUserNames = MibVariable((1, 3, 6, 1, 6, 3, 15, 1, 1, 3), Counter32()).setMaxAccess("readonly") +usmStatsUnknownEngineIDs = MibVariable((1, 3, 6, 1, 6, 3, 15, 1, 1, 4), Counter32()).setMaxAccess("readonly") +usmStatsWrongDigests = MibVariable((1, 3, 6, 1, 6, 3, 15, 1, 1, 5), Counter32()).setMaxAccess("readonly") +usmStatsDecryptionErrors = MibVariable((1, 3, 6, 1, 6, 3, 15, 1, 1, 6), Counter32()).setMaxAccess("readonly") +usmUser = MibIdentifier((1, 3, 6, 1, 6, 3, 15, 1, 2)) +usmUserSpinLock = MibVariable((1, 3, 6, 1, 6, 3, 15, 1, 2, 1), TestAndIncr()).setMaxAccess("readcreate") +usmUserTable = MibTable((1, 3, 6, 1, 6, 3, 15, 1, 2, 2)) +usmUserEntry = MibTableRow((1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1)).setIndexNames((0, "SNMP-USER-BASED-SM-MIB", "usmUserEngineID"), (0, "SNMP-USER-BASED-SM-MIB", "usmUserName")) +usmUserEngineID = MibTableColumn((1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 1)).setColumnInitializer(MibVariable((), SnmpEngineID()).setMaxAccess("noaccess")) +usmUserName = MibTableColumn((1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 2)).setColumnInitializer(MibVariable((), SnmpAdminString().addConstraints(subtypes.ValueRangeConstraint(1, 32))).setMaxAccess("noaccess")) +usmUserSecurityName = MibTableColumn((1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 3)).setColumnInitializer(MibVariable((), SnmpAdminString()).setMaxAccess("readonly")) +usmUserCloneFrom = MibTableColumn((1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 4)).setColumnInitializer(MibVariable((), RowPointer()).setMaxAccess("readcreate")) +usmUserAuthProtocol = MibTableColumn((1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 5)).setColumnInitializer(MibVariable((), AutonomousType()).setMaxAccess("readcreate")) +usmUserAuthKeyChange = MibTableColumn((1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 6)).setColumnInitializer(MibVariable((), KeyChange()).setMaxAccess("readcreate")) +usmUserOwnAuthKeyChange = MibTableColumn((1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 7)).setColumnInitializer(MibVariable((), KeyChange()).setMaxAccess("readcreate")) +usmUserPrivProtocol = MibTableColumn((1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 8)).setColumnInitializer(MibVariable((), AutonomousType()).setMaxAccess("readcreate")) +usmUserPrivKeyChange = MibTableColumn((1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 9)).setColumnInitializer(MibVariable((), KeyChange()).setMaxAccess("readcreate")) +usmUserOwnPrivKeyChange = MibTableColumn((1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 10)).setColumnInitializer(MibVariable((), KeyChange()).setMaxAccess("readcreate")) +usmUserPublic = MibTableColumn((1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 11)).setColumnInitializer(MibVariable((), OctetString().addConstraints(subtypes.ValueRangeConstraint(0, 32)).set('')).setMaxAccess("readcreate")) +usmUserStorageType = MibTableColumn((1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 12)).setColumnInitializer(MibVariable((), StorageType()).setMaxAccess("readcreate")) +usmUserStatus = MibTableColumn((1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 13)).setColumnInitializer(MibVariable((), RowStatus()).setMaxAccess("readcreate")) +usmMIBConformance = MibIdentifier((1, 3, 6, 1, 6, 3, 15, 2)) +usmMIBCompliances = MibIdentifier((1, 3, 6, 1, 6, 3, 15, 2, 1)) +usmMIBGroups = MibIdentifier((1, 3, 6, 1, 6, 3, 15, 2, 2)) + +# Augmentions + +# Groups + +usmMIBBasicGroup = ObjectGroup((1, 3, 6, 1, 6, 3, 15, 2, 2, 1)).setObjects(("SNMP-USER-BASED-SM-MIB", "usmStatsUnknownEngineIDs"), ("SNMP-USER-BASED-SM-MIB", "usmUserOwnAuthKeyChange"), ("SNMP-USER-BASED-SM-MIB", "usmStatsNotInTimeWindows"), ("SNMP-USER-BASED-SM-MIB", "usmStatsUnknownUserNames"), ("SNMP-USER-BASED-SM-MIB", "usmStatsDecryptionErrors"), ("SNMP-USER-BASED-SM-MIB", "usmStatsUnsupportedSecLevels"), ("SNMP-USER-BASED-SM-MIB", "usmUserSecurityName"), ("SNMP-USER-BASED-SM-MIB", "usmUserStatus"), ("SNMP-USER-BASED-SM-MIB", "usmUserPrivKeyChange"), ("SNMP-USER-BASED-SM-MIB", "usmUserOwnPrivKeyChange"), ("SNMP-USER-BASED-SM-MIB", "usmUserStorageType"), ("SNMP-USER-BASED-SM-MIB", "usmUserSpinLock"), ("SNMP-USER-BASED-SM-MIB", "usmUserAuthKeyChange"), ("SNMP-USER-BASED-SM-MIB", "usmUserCloneFrom"), ("SNMP-USER-BASED-SM-MIB", "usmUserPrivProtocol"), ("SNMP-USER-BASED-SM-MIB", "usmUserAuthProtocol"), ("SNMP-USER-BASED-SM-MIB", "usmStatsWrongDigests"), ("SNMP-USER-BASED-SM-MIB", "usmUserPublic"), ) + +# Exports + +# Types +mibBuilder.exportSymbols("SNMP-USER-BASED-SM-MIB", KeyChange=KeyChange) + +# Objects +mibBuilder.exportSymbols("SNMP-USER-BASED-SM-MIB", usmNoAuthProtocol=usmNoAuthProtocol, usmHMACMD5AuthProtocol=usmHMACMD5AuthProtocol, usmHMACSHAAuthProtocol=usmHMACSHAAuthProtocol, usmNoPrivProtocol=usmNoPrivProtocol, usmDESPrivProtocol=usmDESPrivProtocol, snmpUsmMIB=snmpUsmMIB, usmMIBObjects=usmMIBObjects, usmStats=usmStats, usmStatsUnsupportedSecLevels=usmStatsUnsupportedSecLevels, usmStatsNotInTimeWindows=usmStatsNotInTimeWindows, usmStatsUnknownUserNames=usmStatsUnknownUserNames, usmStatsUnknownEngineIDs=usmStatsUnknownEngineIDs, usmStatsWrongDigests=usmStatsWrongDigests, usmStatsDecryptionErrors=usmStatsDecryptionErrors, usmUser=usmUser, usmUserSpinLock=usmUserSpinLock, usmUserTable=usmUserTable, usmUserEntry=usmUserEntry, usmUserEngineID=usmUserEngineID, usmUserName=usmUserName, usmUserSecurityName=usmUserSecurityName, usmUserCloneFrom=usmUserCloneFrom, usmUserAuthProtocol=usmUserAuthProtocol, usmUserAuthKeyChange=usmUserAuthKeyChange, usmUserOwnAuthKeyChange=usmUserOwnAuthKeyChange, usmUserPrivProtocol=usmUserPrivProtocol, usmUserPrivKeyChange=usmUserPrivKeyChange, usmUserOwnPrivKeyChange=usmUserOwnPrivKeyChange, usmUserPublic=usmUserPublic, usmUserStorageType=usmUserStorageType, usmUserStatus=usmUserStatus, usmMIBConformance=usmMIBConformance, usmMIBCompliances=usmMIBCompliances, usmMIBGroups=usmMIBGroups) + +# Groups +mibBuilder.exportSymbols("SNMP-USER-BASED-SM-MIB", usmMIBBasicGroup=usmMIBBasicGroup) diff --git a/pysnmp/smi/mibs/SNMP-VIEW-BASED-ACM-MIB.py b/pysnmp/smi/mibs/SNMP-VIEW-BASED-ACM-MIB.py new file mode 100644 index 00000000..7733f03d --- /dev/null +++ b/pysnmp/smi/mibs/SNMP-VIEW-BASED-ACM-MIB.py @@ -0,0 +1,67 @@ +# PySNMP SMI module. Autogenerated from smidump -f python SNMP-VIEW-BASED-ACM-MIB +# by libsmi2pysnmp-0.0.3-alpha at Wed Nov 10 13:12:27 2004, +# Python version (2, 2, 1, 'final', 0) + +# Imported just in case new ASN.1 types would be created +from pysnmp.asn1 import subtypes + +# Imports + +( Integer, ObjectIdentifier, OctetString, ) = mibBuilder.importSymbols("ASN1", "Integer", "ObjectIdentifier", "OctetString") +( SnmpAdminString, SnmpSecurityLevel, SnmpSecurityModel, ) = mibBuilder.importSymbols("SNMP-FRAMEWORK-MIB", "SnmpAdminString", "SnmpSecurityLevel", "SnmpSecurityModel") +( ModuleCompliance, ObjectGroup, ) = mibBuilder.importSymbols("SNMPv2-CONF", "ModuleCompliance", "ObjectGroup") +( Bits, Integer32, ModuleIdentity, MibIdentifier, MibVariable, MibTable, MibTableRow, MibTableColumn, TimeTicks, snmpModules, ) = mibBuilder.importSymbols("SNMPv2-SMI", "Bits", "Integer32", "ModuleIdentity", "MibIdentifier", "MibVariable", "MibTable", "MibTableRow", "MibTableColumn", "TimeTicks", "snmpModules") +( RowStatus, StorageType, TestAndIncr, ) = mibBuilder.importSymbols("SNMPv2-TC", "RowStatus", "StorageType", "TestAndIncr") + +# Objects + +snmpVacmMIB = ModuleIdentity((1, 3, 6, 1, 6, 3, 16)) +vacmMIBObjects = MibIdentifier((1, 3, 6, 1, 6, 3, 16, 1)) +vacmContextTable = MibTable((1, 3, 6, 1, 6, 3, 16, 1, 1)) +vacmContextEntry = MibTableRow((1, 3, 6, 1, 6, 3, 16, 1, 1, 1)).setIndexNames((0, "SNMP-VIEW-BASED-ACM-MIB", "vacmContextName")) +vacmContextName = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 1, 1, 1)).setColumnInitializer(MibVariable((), SnmpAdminString().addConstraints(subtypes.ValueRangeConstraint(0, 32))).setMaxAccess("readonly")) +vacmSecurityToGroupTable = MibTable((1, 3, 6, 1, 6, 3, 16, 1, 2)) +vacmSecurityToGroupEntry = MibTableRow((1, 3, 6, 1, 6, 3, 16, 1, 2, 1)).setIndexNames((0, "SNMP-VIEW-BASED-ACM-MIB", "vacmSecurityModel"), (0, "SNMP-VIEW-BASED-ACM-MIB", "vacmSecurityName")) +vacmSecurityModel = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 2, 1, 1)).setColumnInitializer(MibVariable((), SnmpSecurityModel().addConstraints(subtypes.ValueRangeConstraint(1, 2147483647L))).setMaxAccess("noaccess")) +vacmSecurityName = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 2, 1, 2)).setColumnInitializer(MibVariable((), SnmpAdminString().addConstraints(subtypes.ValueRangeConstraint(1, 32))).setMaxAccess("noaccess")) +vacmGroupName = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 2, 1, 3)).setColumnInitializer(MibVariable((), SnmpAdminString().addConstraints(subtypes.ValueRangeConstraint(1, 32))).setMaxAccess("readcreate")) +vacmSecurityToGroupStorageType = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 2, 1, 4)).setColumnInitializer(MibVariable((), StorageType()).setMaxAccess("readcreate")) +vacmSecurityToGroupStatus = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 2, 1, 5)).setColumnInitializer(MibVariable((), RowStatus()).setMaxAccess("readcreate")) +vacmAccessTable = MibTable((1, 3, 6, 1, 6, 3, 16, 1, 4)) +vacmAccessEntry = MibTableRow((1, 3, 6, 1, 6, 3, 16, 1, 4, 1)).setIndexNames((0, "SNMP-VIEW-BASED-ACM-MIB", "vacmGroupName"), (0, "SNMP-VIEW-BASED-ACM-MIB", "vacmAccessContextPrefix"), (0, "SNMP-VIEW-BASED-ACM-MIB", "vacmAccessSecurityModel"), (0, "SNMP-VIEW-BASED-ACM-MIB", "vacmAccessSecurityLevel")) +vacmAccessContextPrefix = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 1)).setColumnInitializer(MibVariable((), SnmpAdminString().addConstraints(subtypes.ValueRangeConstraint(0, 32))).setMaxAccess("noaccess")) +vacmAccessSecurityModel = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 2)).setColumnInitializer(MibVariable((), SnmpSecurityModel()).setMaxAccess("noaccess")) +vacmAccessSecurityLevel = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 3)).setColumnInitializer(MibVariable((), SnmpSecurityLevel()).setMaxAccess("noaccess")) +vacmAccessContextMatch = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 4)).setColumnInitializer(MibVariable((), Integer().addConstraints(subtypes.SingleValueConstraint(2,1,)).addNamedValues(("exact", 1), ("prefix", 2), ).set(1)).setMaxAccess("readcreate")) +vacmAccessReadViewName = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 5)).setColumnInitializer(MibVariable((), SnmpAdminString().addConstraints(subtypes.ValueRangeConstraint(0, 32)).set('')).setMaxAccess("readcreate")) +vacmAccessWriteViewName = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 6)).setColumnInitializer(MibVariable((), SnmpAdminString().addConstraints(subtypes.ValueRangeConstraint(0, 32)).set('')).setMaxAccess("readcreate")) +vacmAccessNotifyViewName = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 7)).setColumnInitializer(MibVariable((), SnmpAdminString().addConstraints(subtypes.ValueRangeConstraint(0, 32)).set('')).setMaxAccess("readcreate")) +vacmAccessStorageType = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 8)).setColumnInitializer(MibVariable((), StorageType()).setMaxAccess("readcreate")) +vacmAccessStatus = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 9)).setColumnInitializer(MibVariable((), RowStatus()).setMaxAccess("readcreate")) +vacmMIBViews = MibIdentifier((1, 3, 6, 1, 6, 3, 16, 1, 5)) +vacmViewSpinLock = MibVariable((1, 3, 6, 1, 6, 3, 16, 1, 5, 1), TestAndIncr()).setMaxAccess("readcreate") +vacmViewTreeFamilyTable = MibTable((1, 3, 6, 1, 6, 3, 16, 1, 5, 2)) +vacmViewTreeFamilyEntry = MibTableRow((1, 3, 6, 1, 6, 3, 16, 1, 5, 2, 1)).setIndexNames((0, "SNMP-VIEW-BASED-ACM-MIB", "vacmViewTreeFamilyViewName"), (0, "SNMP-VIEW-BASED-ACM-MIB", "vacmViewTreeFamilySubtree")) +vacmViewTreeFamilyViewName = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 5, 2, 1, 1)).setColumnInitializer(MibVariable((), SnmpAdminString().addConstraints(subtypes.ValueRangeConstraint(1, 32))).setMaxAccess("noaccess")) +vacmViewTreeFamilySubtree = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 5, 2, 1, 2)).setColumnInitializer(MibVariable((), ObjectIdentifier()).setMaxAccess("noaccess")) +vacmViewTreeFamilyMask = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 5, 2, 1, 3)).setColumnInitializer(MibVariable((), OctetString().addConstraints(subtypes.ValueRangeConstraint(0, 16)).set('')).setMaxAccess("readcreate")) +vacmViewTreeFamilyType = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 5, 2, 1, 4)).setColumnInitializer(MibVariable((), Integer().addConstraints(subtypes.SingleValueConstraint(1,2,)).addNamedValues(("included", 1), ("excluded", 2), ).set(1)).setMaxAccess("readcreate")) +vacmViewTreeFamilyStorageType = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 5, 2, 1, 5)).setColumnInitializer(MibVariable((), StorageType()).setMaxAccess("readcreate")) +vacmViewTreeFamilyStatus = MibTableColumn((1, 3, 6, 1, 6, 3, 16, 1, 5, 2, 1, 6)).setColumnInitializer(MibVariable((), RowStatus()).setMaxAccess("readcreate")) +vacmMIBConformance = MibIdentifier((1, 3, 6, 1, 6, 3, 16, 2)) +vacmMIBCompliances = MibIdentifier((1, 3, 6, 1, 6, 3, 16, 2, 1)) +vacmMIBGroups = MibIdentifier((1, 3, 6, 1, 6, 3, 16, 2, 2)) + +# Augmentions + +# Groups + +vacmBasicGroup = ObjectGroup((1, 3, 6, 1, 6, 3, 16, 2, 2, 1)).setObjects(("SNMP-VIEW-BASED-ACM-MIB", "vacmViewTreeFamilyStorageType"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmAccessContextMatch"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmViewTreeFamilyStatus"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmAccessNotifyViewName"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmAccessReadViewName"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmViewTreeFamilyType"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmAccessStatus"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmGroupName"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmViewTreeFamilyMask"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmViewSpinLock"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmSecurityToGroupStorageType"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmSecurityToGroupStatus"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmAccessStorageType"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmContextName"), ("SNMP-VIEW-BASED-ACM-MIB", "vacmAccessWriteViewName"), ) + +# Exports + +# Objects +mibBuilder.exportSymbols("SNMP-VIEW-BASED-ACM-MIB", snmpVacmMIB=snmpVacmMIB, vacmMIBObjects=vacmMIBObjects, vacmContextTable=vacmContextTable, vacmContextEntry=vacmContextEntry, vacmContextName=vacmContextName, vacmSecurityToGroupTable=vacmSecurityToGroupTable, vacmSecurityToGroupEntry=vacmSecurityToGroupEntry, vacmSecurityModel=vacmSecurityModel, vacmSecurityName=vacmSecurityName, vacmGroupName=vacmGroupName, vacmSecurityToGroupStorageType=vacmSecurityToGroupStorageType, vacmSecurityToGroupStatus=vacmSecurityToGroupStatus, vacmAccessTable=vacmAccessTable, vacmAccessEntry=vacmAccessEntry, vacmAccessContextPrefix=vacmAccessContextPrefix, vacmAccessSecurityModel=vacmAccessSecurityModel, vacmAccessSecurityLevel=vacmAccessSecurityLevel, vacmAccessContextMatch=vacmAccessContextMatch, vacmAccessReadViewName=vacmAccessReadViewName, vacmAccessWriteViewName=vacmAccessWriteViewName, vacmAccessNotifyViewName=vacmAccessNotifyViewName, vacmAccessStorageType=vacmAccessStorageType, vacmAccessStatus=vacmAccessStatus, vacmMIBViews=vacmMIBViews, vacmViewSpinLock=vacmViewSpinLock, vacmViewTreeFamilyTable=vacmViewTreeFamilyTable, vacmViewTreeFamilyEntry=vacmViewTreeFamilyEntry, vacmViewTreeFamilyViewName=vacmViewTreeFamilyViewName, vacmViewTreeFamilySubtree=vacmViewTreeFamilySubtree, vacmViewTreeFamilyMask=vacmViewTreeFamilyMask, vacmViewTreeFamilyType=vacmViewTreeFamilyType, vacmViewTreeFamilyStorageType=vacmViewTreeFamilyStorageType, vacmViewTreeFamilyStatus=vacmViewTreeFamilyStatus, vacmMIBConformance=vacmMIBConformance, vacmMIBCompliances=vacmMIBCompliances, vacmMIBGroups=vacmMIBGroups) + +# Groups +mibBuilder.exportSymbols("SNMP-VIEW-BASED-ACM-MIB", vacmBasicGroup=vacmBasicGroup) diff --git a/pysnmp/smi/mibs/SNMPv2-CONF.py b/pysnmp/smi/mibs/SNMPv2-CONF.py new file mode 100644 index 00000000..d177aad6 --- /dev/null +++ b/pysnmp/smi/mibs/SNMPv2-CONF.py @@ -0,0 +1,21 @@ + +( MibNodeBase, + NotificationType ) = mibBuilder.importSymbols( + 'SNMPv2-SMI', + 'MibNodeBase', + 'NotificationType' + ) + +class ObjectGroup(NotificationType): pass +class NotificationGroup(NotificationType): pass +class ModuleCompliance(MibNodeBase): pass +class AgentCapabilities(MibNodeBase): pass + +mibBuilder.exportSymbols( + 'SNMPv2-CONF', + ObjectGroup=ObjectGroup, + NotificationGroup=NotificationGroup, + ModuleCompliance=ModuleCompliance, + AgentCapabilities=AgentCapabilities + ) + diff --git a/pysnmp/smi/mibs/SNMPv2-MIB.py b/pysnmp/smi/mibs/SNMPv2-MIB.py new file mode 100644 index 00000000..41a007bc --- /dev/null +++ b/pysnmp/smi/mibs/SNMPv2-MIB.py @@ -0,0 +1,145 @@ +try: + from socket import gethostname +except: + gethostname = lambda x="": x +from time import time +from sys import version +from pysnmp.version import getVersion +from pysnmp.asn1 import subtypes + +Integer, ObjectIdentifier, = mibBuilder.importSymbols( + 'ASN1', 'Integer', 'ObjectIdentifier' + ) +ModuleIdentity, ObjectIdentity, MibIdentifier, \ + MibVariable, MibTable, MibTableRow, MibTableColumn, \ + NotificationType, TimeTicks, Counter32, \ + snmpModules, mib_2 = mibBuilder.importSymbols( + 'SNMPv2-SMI', 'ModuleIdentity', 'ObjectIdentity', + 'MibIdentifier', 'MibVariable', 'MibTable', 'MibTableRow', + 'MibTableColumn', 'NotificationType', 'TimeTicks', 'Counter32', + 'snmpModules', 'mib-2' + ) + +DisplayString, TestAndIncr, TimeStamp = mibBuilder.importSymbols( + 'SNMPv2-TC', 'DisplayString', 'TestAndIncr', 'TimeStamp' + ) + +snmpMIB = ModuleIdentity(snmpModules.name + (1,)) +snmpMIBObjects = MibIdentifier(snmpMIB.name + (1,)) +system = MibIdentifier(mib_2.name + (1,)) + +sysDescr = MibVariable(system.name + (1,), DisplayString("PySNMP engine version %s.%s.%s, Python %s" % (getVersion() + (version,))).addConstraints(subtypes.ValueSizeConstraint(0, 255))).setMaxAccess('readonly') + +sysObjectID = MibVariable(system.name + (2,), ObjectIdentifier((1,3,6,1,4,1,20408))).setMaxAccess('readonly') + +class __SysUpTime(TimeTicks): + initialValue = int(time()) + def get(self): return (int(time()) - TimeTicks.get(self))*100 + +sysUpTime = MibVariable(system.name + (3,), __SysUpTime()).setMaxAccess('readonly') + +sysContact = MibVariable(system.name + (4,), DisplayString("").addConstraints(subtypes.ValueSizeConstraint(0, 255))).setMaxAccess('readonly') + +sysName = MibVariable(system.name + (5,), DisplayString(gethostname()).addConstraints(subtypes.ValueSizeConstraint(0, 255))).setMaxAccess('readonly') + +sysLocation = MibVariable(system.name + (6,), DisplayString("").addConstraints(subtypes.ValueSizeConstraint(0, 255))).setMaxAccess('readonly') + +sysServices = MibVariable(system.name + (7,), Integer(72).addConstraints(subtypes.ValueRangeConstraint(0, 127))).setMaxAccess('readonly') + +sysORLastChange = MibVariable(system.name + (8,), TimeStamp()).setMaxAccess('readonly') + +# sysORTable + +sysORTable = MibTable(system.name + (9,)) +sysOREntry = MibTableRow(sysORTable.name + (1,)).setIndexNames((0, 'SNMPv2-MIB', 'sysORIndex')) + +sysORIndex = MibTableColumn(sysOREntry.name + (1,)).setColumnInitializer(MibVariable((), Integer().addConstraints(subtypes.ValueRangeConstraint(1, 2147483647))).setMaxAccess('noaccess')) + +sysORID = MibTableColumn(sysOREntry.name + (2,)).setColumnInitializer(MibVariable((), ObjectIdentifier()).setMaxAccess('readcreate')) + +sysORDescr = MibTableColumn(sysOREntry.name + (3,)).setColumnInitializer(MibVariable((), DisplayString()).setMaxAccess('readcreate')) + +sysORUpTime = MibTableColumn(sysOREntry.name + (4,)).setColumnInitializer(MibVariable((), TimeStamp()).setMaxAccess('readcreate')) + +# the SNMP group + +snmp = MibIdentifier(mib_2.name + (11,)) + +snmpInPkts = MibVariable(snmp.name + (1,), Counter32()).setMaxAccess('readonly') + +snmpInBadVersions = MibVariable(snmp.name + (3,), Counter32()).setMaxAccess('readonly') + +snmpInBadCommunityNames = MibVariable(snmp.name + (4,), Counter32()).setMaxAccess('readonly') + +snmpInBadCommunityUses = MibVariable(snmp.name + (5,), Counter32()).setMaxAccess('readonly') + +snmpInASNParseErrs = MibVariable(snmp.name + (6,), Counter32()).setMaxAccess('readonly') + +snmpEnableAuthenTraps = MibVariable(snmp.name + (30,), Integer().addConstraints(subtypes.SingleValueConstraint(1, 2))).setMaxAccess('readwrite') + +snmpSilentDrops = MibVariable(snmp.name + (31,), Counter32()).setMaxAccess('readonly') + +snmpProxyDrops = MibVariable(snmp.name + (32,), Counter32()).setMaxAccess('readonly') + +# information for notifications + +snmpTrap = MibIdentifier(snmpMIBObjects.name + (4,)) + +snmpTrapOID = MibVariable(snmpTrap.name + (1,), ObjectIdentifier()).setMaxAccess('notifyonly') + +snmpTrapEnterprise = MibVariable(snmpTrap.name + (3,), ObjectIdentifier()).setMaxAccess('notifyonly') + +# well-known traps + +snmpTraps = MibIdentifier(snmpMIBObjects.name + (5,)) + +coldStart = NotificationType(snmpTraps.name + (1,)) + +warmStart = NotificationType(snmpTraps.name + (2,)) + +authenticationFailure = NotificationType(snmpTraps.name + (5,)) + +# the set group + +snmpSet = MibIdentifier(snmpMIBObjects.name + (6,)) + +snmpSetSerialNo = MibVariable(snmpSet.name + (1,), TestAndIncr()).setMaxAccess('readwrite') + +mibBuilder.exportSymbols( + 'SNMPv2-MIB', + snmpMIB=snmpMIB, + snmpMIBObjects=snmpMIBObjects, + system=system, + sysDescr=sysDescr, + sysObjectID=sysObjectID, + sysUpTime=sysUpTime, + sysContact=sysContact, + sysName=sysName, + sysLocation=sysLocation, + sysServices=sysServices, + sysORLastChange=sysORLastChange, + sysORTable=sysORTable, + sysOREntry=sysOREntry, + sysORIndex=sysORIndex, + sysORID=sysORID, + sysORDescr=sysORDescr, + sysORUpTime=sysORUpTime, + snmp=snmp, + snmpInPkts=snmpInPkts, + snmpInBadVersions=snmpInBadVersions, + snmpInBadCommunityNames=snmpInBadCommunityNames, + snmpInBadCommunityUses=snmpInBadCommunityUses, + snmpInASNParseErrs=snmpInASNParseErrs, + snmpEnableAuthenTraps=snmpEnableAuthenTraps, + snmpSilentDrops=snmpSilentDrops, + snmpProxyDrops=snmpProxyDrops, + snmpTrap=snmpTrap, + snmpTrapOID=snmpTrapOID, + snmpTrapEnterprise=snmpTrapEnterprise, + snmpTraps=snmpTraps, + coldStart=coldStart, + warmStart=warmStart, + authenticationFailure=authenticationFailure, + snmpSet=snmpSet, + snmpSetSerialNo=snmpSetSerialNo + ) diff --git a/pysnmp/smi/mibs/SNMPv2-SMI.py b/pysnmp/smi/mibs/SNMPv2-SMI.py new file mode 100644 index 00000000..356b3d68 --- /dev/null +++ b/pysnmp/smi/mibs/SNMPv2-SMI.py @@ -0,0 +1,851 @@ +from string import join, split +from pysnmp.smi.indices import OidOrderedDict +from pysnmp.smi import error +from pysnmp.proto import rfc1902 +from pysnmp.asn1 import subtypes +from pysnmp.asn1.error import ValueConstraintError + +( OctetString, + ObjectIdentifier, + Integer ) = mibBuilder.importSymbols( + 'ASN1', + 'OctetString', + 'ObjectIdentifier', + 'Integer' + ) + +# syntax of objects + +Bits = rfc1902.Bits +Integer32 = rfc1902.Integer32 +IpAddress = rfc1902.IpAddress +Counter32 = rfc1902.Counter32 +Gauge32 = rfc1902.Gauge32 +Unsigned32 = rfc1902.Unsigned32 +TimeTicks = rfc1902.TimeTicks +Opaque = rfc1902.Opaque +Counter64 = rfc1902.Counter64 + +class ExtUTCTime(OctetString): + subtypeConstraints = OctetString.subtypeConstraints + ( + subtypes.ValueSizeConstraint(0, 13), + ) + +# MIB tree foundation classes + +class MibNodeBase: + def __init__(self, name=()): + self.name = name + self.label = '' + + def __repr__(self): + return '%s(%s)' % (self.__class__.__name__, self.name) + + def setName(self, name): + self.name = name + return self + + def setLabel(self, label): + self.label = label + return self + + def clone(self, name=None): + myClone = self.__class__(self.name) + if name is not None: + myClone.name = name + if self.label is not None: + myClone.label = self.label + return myClone + +# definitions for information modules + +class ModuleIdentity(MibNodeBase): + def getLastUpdated(self): + return getattr(self, 'lastUpdated', '') + def setLastUpdated(self, v): + self.lastUpdated = v + return self + def getOrganization(self): + return getattr(self, 'organization', '') + def setOrganization(self, v): + self.organization = v + return self + def getContactInfo(self): + return getattr(self, 'contactInfo', '') + def setContactInfo(self, v): + self.contactInfo = v + return self + def getDescription(self): + return getattr(self, 'description', '') + def setDescription(self, v): + self.description = v + return self + def getRevisions(self): + return getattr(self, 'revisions', ()) + def setRevisions(self, *args): + self.revisions = args + return self + +class ObjectIdentity(MibNodeBase): + def getStatus(self): + return getattr(self, 'status', 'current') + def setStatus(self, v): + self.status = v + return self + def getDescription(self): + return getattr(self, 'description', '') + def setDescription(self, v): + self.description = v + return self + def getReference(self): + return getattr(self, 'reference', '') + def setReference(self, v): + self.reference = v + return self + +# definition for objects + +class NotificationType(MibNodeBase): + def getObjects(self): + return getattr(self, 'objects', ()) + def setObjects(self, *args): + self.objects = args + return self + def getStatus(self): + return getattr(self, 'status', 'current') + def setStatus(self, v): + self.status = v + return self + def getDescription(self): + return getattr(self, 'description', '') + def setDescription(self, v): + self.description = v + return self + def getRevisions(self): + return getattr(self, 'revisions', ()) + def setRevisions(self, *args): + self.revisions = args + return self + +class MibIdentifier(MibNodeBase): pass + +class ObjectTypePattern(MibNodeBase): + maxAccess = None + def getSyntax(self): + return getattr(self, 'syntax', None) # XXX + def getSyntaxClone(self): + # May be used to preserve backend instrumentation settings + # whenever SNMP engine shares the same MIB for manager & agent roles + if hasattr(self, 'syntaxClone'): + return self.syntaxClone + self.syntaxClone = self.getSyntax() + if self.syntaxClone is not None: + self.syntaxClone = self.syntaxClone.clone() + return self.syntaxClone + def setSyntax(self, v): + self.syntax = v + return self + def getUnits(self): + return getattr(self, 'units', '') + def setUnits(self, v): + self.units = v + return self + def getMaxAccess(self): + return getattr(self, 'maxAccess', 'not-accessible') + def setMaxAccess(self, v): + self.maxAccess = v + return self + def getStatus(self): + return getattr(self, 'status', 'current') + def setStatus(self, v): + self.status = v + return self + def getDescription(self): + return getattr(self, 'description', '') + def setDescription(self, v): + self.description = v + return self + def getReference(self): + return getattr(self, 'reference', '') + def setReference(self, v): + self.reference = v + return self + +class MibVariable(ObjectTypePattern): + """Scalar MIB variable instance. Implements read/write operations.""" + maxAccess = 'readonly' + def __init__(self, name=None, syntax=None): + ObjectTypePattern.__init__(self, name) + if syntax is not None: + self.setSyntax(syntax) + self.__newValue = None + + def __repr__(self): + return '%s(%s, %s)' % ( + self.__class__.__name__, self.name, self.syntax + ) + + def __cmp__(self, other): return cmp(self.syntax, other) + + def clone(self, name=None, syntax=None): + myClone = ObjectTypePattern.clone(self, name) + myClone.maxAccess = self.maxAccess + # XXX constr checking on initialisation + if syntax is not None: + myClone.syntax = syntax + elif self.syntax is not None: + # XXX clone the rest of attrs + myClone.syntax = self.syntax.clone() + return myClone + + def getNode(self, name): + # Recursion terminator + if name == self.name: + return self + raise error.NoSuchInstanceError( + 'No such name %s at %s' % (name, self) + ) + + def getNextNode(self, name): + # Recursion terminator + raise error.NoSuchInstanceError( + 'No next name %s at leaf %s' % (name, self) + ) + + # MIB instrumentation methods + + # Read operation + + def readTest(self, name, val): + if name == self.name: + if self.maxAccess != 'readonly' and \ + self.maxAccess != 'readwrite' and \ + self.maxAccess != 'readcreate': + raise error.NoAccessError( + 'No read access to variable %s' % str(name) + ) + else: + raise error.NoSuchInstanceError( + 'Variable %s does not exist at %s' % (name, self) + ) + + def readGet(self, name, val): + # Return current variable (name, value). This is the only API method + # capable of returning anything! + if name == self.name: + return self.name, self.syntax + + # Two-phase commit implementation + + def writeTest(self, name, val): + # Make sure write's allowed + if name == self.name: + # make sure variable is writable + if self.maxAccess != 'readwrite' and \ + self.maxAccess != 'readcreate': + raise error.NotWritableError( + 'No write access to variable %s at %s' % (name, self) + ) + else: + raise error.NoSuchInstanceError( + 'Variable %s does not exist at %s' % (name, self) + ) + self.__newSyntax = self.syntax.clone() + self.__newSyntax.set(val) + + def writeCommit(self, name, val): + # Commit new value + self.syntax, self.__newSyntax = self.__newSyntax, self.syntax + + def writeCleanup(self, name, val): + # Drop previous value + self.__newSyntax = None + + def writeUndo(self, name, val): + # Revive previous value + self.syntax, self.__newSyntax = self.__newSyntax, None + +class MibTree(ObjectTypePattern): + branchVersionId = 0L # increments on tree structure change XXX + defaultVars = None + maxAccess = 'not-accessible' + def __init__(self, name=None, *vars): + ObjectTypePattern.__init__(self, name) + self._vars = OidOrderedDict() + if vars: + apply(self.registerSubtrees, vars) + if self.defaultVars: + apply(self.registerSubtrees, + map(lambda x: x.clone(), self.defaultVars) + ) + + # Subtrees registration + + def registerSubtrees(self, *subTrees): + """Register subtrees at this tree. Subtrees are always attached + at the level of this tree, not subtrees.""" + for subTree in subTrees: + if self._vars.has_key(subTree.name): + continue +# XXX complain? +# if self._vars[subTree.name] is subTree: +# continue +# raise error.SmiError( +# 'MIB subtree %s already registered %s' % \ +# (subTree.name, self) +# ) + self._vars[subTree.name] = subTree + MibTree.branchVersionId = MibTree.branchVersionId + 1 + + def unregisterSubtrees(self, *subTrees): + """Detach subtrees from this tree""" + for subTree in subTrees: + if self._vars.has_key(subTree.name): + del self._vars[subTree.name] + MibTree.branchVersionId = MibTree.branchVersionId + 1 + + # Tree traversal + + def getBranch(self, name): + """Return a branch of this tree where the 'name' OID may reside""" + subName = tuple(name) + subNameLen = len(self.name) + while subNameLen < len(subName): + if self._vars.has_key(subName): + return self._vars[subName] + subName = subName[:-1] + else: + raise error.NoSuchInstanceError( + 'Name %s does not exist at %s' % (name, self) + ) + + def getNode(self, name): + """Return tree node found by name""" + if name == self.name: + return self + else: + return self.getBranch(name).getNode(name) + + def getNextNode(self, name): + """Return tree node next to name""" + try: + nextNode = self.getBranch(name) + except error.NoSuchInstanceError: + # Start from the beginning + if self._vars and name <= self._vars.keys()[0]: + return self._vars[self._vars.keys()[0]] + else: + raise + else: + try: + return nextNode.getNextNode(name) + except error.NoSuchInstanceError: + try: + return self._vars[self._vars.nextKey(nextNode.name)] + except KeyError: + raise error.NoSuchInstanceError(name) + + # Mapping interface to subtree XXX + + def get(self, key, defVal=None): return self._vars.get(key, defVal) + def keys(self): return self._vars.keys() + + # MIB instrumentation + + # Read operation + + def readTest(self, name, val): + if name == self.name: + if self.maxAccess != 'readonly' and \ + self.maxAccess != 'readwrite' and \ + self.maxAccess != 'readcreate': + raise error.NoAccessError( + 'No read access to variable at %s' % self + ) + else: + node = self.getBranch(name) + +# XXX +# if not isinstance(node, ObjectTypePattern): +# raise error.NoAccessError( +# 'Not ObjectType macro instance at %s' % self +# ) + node.readTest(name, val) + + def readGet(self, name, val): + return self.getBranch(name).readGet(name, val) + + # Read next operation is subtree-specific + + def readTestNext(self, name, val): + nextName = name + while 1: + nextName = self.getNextNode(nextName).name + try: + return self.readTest(nextName, val) + except error.NoAccessError: + continue + + def readGetNext(self, name, val): + nextName = name + while 1: + nextName = self.getNextNode(nextName).name + if nextName: + try: + self.readTest(nextName, val) # XXX + except error.NoAccessError: + continue + else: + return self.readGet(nextName, val) + else: + raise error.NoSuchInstanceError( + 'Variable next to %s does not exist at %s' % (name, self) + ) + + # Write operation + + def writeTest(self, name, val): + if name == self.name: + # Make sure variable is writable + if self.maxAccess != 'readwrite' and \ + self.maxAccess != 'readcreate': + raise error.NotWritableError( + 'No write access to variable %s at %s' % (name, self) + ) + else: + node = self.getBranch(name) +# XXX +# if not isinstance(node, ObjectTypePattern): # XXX +# raise error.NoAccessError( +# 'Not ObjectType macro instance at %s' % self +# ) + node.writeTest(name, val) + + def writeCommit(self, name, val): + self.getBranch(name).writeCommit(name, val) + + def writeCleanup(self, name, val): + self.getBranch(name).writeCleanup(name, val) + + def writeUndo(self, name, val): + self.getBranch(name).writeUndo(name, val) + +# Conceptual table classes + +class MibTableColumn(MibTree): + """MIB table column. Manages a set of column instance variables""" + defaultColumnInitializer = None + + def __init__(self, name=None, *vars): + apply(MibTree.__init__, (self, name) + vars) + if self.defaultColumnInitializer is not None: + self.setColumnInitializer(self.defaultColumnInitializer.clone()) + else: + self.columnInitializer = None + self.__createdInstances = {}; self.__destroyedInstances = {} + self.__rowOpWanted = {} + + def setColumnInitializer(self, mibVar): + self.columnInitializer = mibVar + self.columnInitializer.name = self.name + return self + + def getColumnInitializer(self): + if self.columnInitializer is None: + raise error.SmiError( + 'Uninitialized column syntax at %s' % (self) + ) + return self.columnInitializer + + def getSyntax(self): + if self.columnInitializer is not None: + return getattr(self.columnInitializer, 'syntax', None) + + # Column creation (this should probably be converted into some state + # machine for clarity). Also, it might be a good idea to inidicate + # defaulted cols creation in a clearer way than just a val == None. + + def createTest(self, name, val=None): + # Make sure creation allowed, create a new column instance but + # do not replace the old one + if self._vars.has_key(name): + return + if val is not None and \ + self.columnInitializer.maxAccess != 'readcreate': + raise error.NoCreationError( + 'Column instance creation prohibited at %s' % self + ) + if not self.__createdInstances.has_key(name): + self.__createdInstances[name] = self.columnInitializer.clone( + name + ) + if val is not None: + try: + self.__createdInstances[name].writeTest(name, val) + except (error.RowCreationWanted, error.RowDestructionWanted): + pass + + def createCommit(self, name, val=None): + # Commit new instance value + if self._vars.has_key(name): + if self.__createdInstances.has_key(name): + if val is not None: + self._vars[name].writeCommit(name, val) + return + if val is not None: + self.__createdInstances[name].writeCommit(name, val) + # ...commit new column instance + self._vars[name], self.__createdInstances[name] = \ + self.__createdInstances[name], self._vars.get(name) + + def createCleanup(self, name, val=None): + # Drop previous column instance + if self.__createdInstances.has_key(name): + if self.__createdInstances[name] is not None: + self.__createdInstances[name].writeCleanup(name, val) + del self.__createdInstances[name] + elif self._vars.has_key(name): + self._vars[name].writeCleanup(name, val) + + def createUndo(self, name, val=None): + # Set back previous column instance, drop the new one + if self.__createdInstances.has_key(name): + self._vars[name] = self.__createdInstances[name] + del self.__createdInstances[name] + # Remove new instance on rollback + if self._vars[name] is None: + del self._vars[name] + else: + self._vars[name].writeUndo(name, val) + + # Column destruction + + def destroyTest(self, name, val=None): + # Make sure destruction is allowed + if self._vars.has_key(name): + if val is not None and \ + self.columnInitializer.maxAccess != 'readcreate': + raise error.NoAccessError( + 'Column instance destruction prohibited at %s' % self + ) + + def destroyCommit(self, name, val=None): + # Make a copy of column instance and take it off the tree + if self._vars.has_key(name): + self.__destroyedInstances[name] = self._vars[name] + del self._vars[name] + + def destroyCleanup(self, name, val=None): + # Drop instance copy + if self.__destroyedInstances.has_key(name): + del self.__destroyedInstances[name] + + def destroyUndo(self, name, val=None): + # Set back column instance + if self.__destroyedInstances.has_key(name): + self._vars[name] = self.__destroyedInstances[name] + del self.__destroyedInstances[name] + + # Set/modify column + + def writeTest(self, name, val): + # Besides common checks, request row creation on no-instance + try: + # First try the instance + MibTree.writeTest(self, name, val) + # ...otherwise proceed with creating new column + except (error.NoSuchInstanceError, error.RowCreationWanted): + self.__rowOpWanted[name] = error.RowCreationWanted() + self.createTest(name, val) + except error.RowDestructionWanted: + self.__rowOpWanted[name] = error.RowDestructionWanted() + self.destroyTest(name, val) + if self.__rowOpWanted.has_key(name): + raise self.__rowOpWanted[name] + + def __delegateWrite(self, subAction, name, val): + if not self.__rowOpWanted.has_key(name): + getattr(MibTree, 'write'+subAction)(self, name, val) + return + if isinstance(self.__rowOpWanted[name], error.RowCreationWanted): + getattr(self, 'create'+subAction)(name, val) + if isinstance(self.__rowOpWanted[name], error.RowDestructionWanted): + getattr(self, 'destroy'+subAction)(name, val) + raise self.__rowOpWanted[name] + + def writeCommit(self, name, val): + self.__delegateWrite('Commit', name, val) + + def writeCleanup(self, name, val): + self.__delegateWrite('Cleanup', name, val) + if self.__rowOpWanted.has_key(name): + del self.__rowOpWanted[name] + + def writeUndo(self, name, val): + self.__delegateWrite('Undo', name, val) + if self.__rowOpWanted.has_key(name): + del self.__rowOpWanted[name] + +class MibTableRow(MibTree): + """MIB table row (SMI 'Entry'). Manages a set of table columns. + Implements row creation/destruction. + """ + defaultIndexNames = None # XXX indexNames ? + + def __init__(self, name=None, *vars): + apply(MibTree.__init__, (self, name) + vars) + if self.defaultIndexNames is not None: + self.setIndexNames(self.defaultIndexNames) + else: + self.indexNames = () + self.augmentingRows = {} + + # Table indices resolution + + __intValue = Integer() + __strValue = OctetString() + __oidValue = ObjectIdentifier() + __ipaddrValue = IpAddress() + + def setFromName(self, obj, value, impliedFlag=None): + if self.__intValue.isSubtype(obj): + obj.set(value[0]) + return value[1:] + elif self.__ipaddrValue.isSubtype(obj): + obj.set(join(map(str, value[:4]), '.')) + return value[4:] + elif self.__strValue.isSubtype(obj): + if impliedFlag: + s = reduce(lambda x,y: x+y, map(lambda x: chr(x), value)) + else: + s = reduce(lambda x,y: x+y, map(lambda x: chr(x), value[1:])) + # XXX check name vs str length + valueLength = len(s) + while valueLength: + try: + obj.set(s[:valueLength]) + s = s[valueLength:] + # XXX + if impliedFlag: + initial = () + else: + initial = (len(obj),) + return reduce( + lambda x,y: x+(y,), map(lambda x: ord(x), s), initial + ) + except ValueConstraintError: + valueLength = valueLength - 1 + raise error.SmiError( + 'Instance ID %s does not fit INDEX %s' % (value, obj) + ) + elif self.__oidValue.isSubtype(obj): + if impliedFlag: + obj.set(value) + else: + obj.set(value[1:]) + return () + else: + obj.set(value) + return () + + def getAsName(self, obj, impliedFlag=None): + if self.__intValue.isSubtype(obj): + return (obj.get()) + elif self.__strValue.isSubtype(obj): + if impliedFlag: + initial = () + else: + initial = (len(obj),) + return reduce( + lambda x,y: x+(y,), map(lambda x: ord(x), obj), initial + ) + elif self.__oidValue.isSubtype(obj): + if impliedFlag: + return tuple(self) + else: + return (len(self),) + tuple(self) + elif self.__ipaddrValue.isSubtype(obj): + return tuple(map(int, split(obj.get(), '.'))) + else: + return (obj.get()) + + # Fate sharing mechanics + + def announceManagementEvent(self, action, name): + # Convert OID suffix into index vals + instId = name[len(self.name)+1:] + baseIndices = [] + for impliedFlag, modName, symName in self.indexNames: + mibObj, = mibBuilder.importSymbols(modName, symName) + instId = self.setFromName( + mibObj.getColumnInitializer().syntax, instId, impliedFlag + ) + if self.name == mibObj.name[:-1]: + baseIndices.append(mibObj) + if instId: + raise error.SmiError( + 'Exsessive instance identifier sub-OIDs left at %s: %s' % + (self, instId) + ) + if not baseIndices: + return + for modName, mibSym in self.augmentingRows.keys(): + mibObj, = mibBuilder.importSymbols(modName, mibSym) + mibObj.receiveManagementEvent(action, baseIndices) + + def receiveManagementEvent(self, action, baseIndices): + # The default implementation supports one-to-one rows dependency + newSuffix = () + # Resolve indices intersection + for impliedFlag, mibMod, symName in self.indexNames: + mibObj, = mibBuilder.importSymbols(modName, symName) + for baseIndex in baseIndices: + if baseIndex.name == mibObj.name: + newSuffix = newSuffix + \ + self.getAsName( + baseIndex.getColumnInitializer().syntax, impliedFlag + ) + if newSuffix: + self.__manageColumns(action, newSuffix) + + def registerAugmentions(self, *names): + for modName, symName in names: + if self.augmentingRows.has_key((modName, symName)): + raise error.SmiError( + 'Row %s already augmented by %s::%s' % \ + (self.name, modName, symName) + ) + self.augmentingRows[(modName, symName)] = 1 + return self + + def setIndexNames(self, *names): + for name in names: +# if name in self.indexNames: +# raise error.SmiError( +# 'Index %s already set to row %s' % ( +# name, self +# )) + self.indexNames = self.indexNames + (name,) + return self + + def getIndexNames(self): + return self.indexNames + + def __manageColumns(self, action, nameSuffix): + for name, var in self._vars.items(): + getattr(var, action)(name + nameSuffix) + + def __delegate(self, subAction, name, val): + # Relay operation request to column, expect row operation request. + + try: + getattr(self.getBranch(name), 'write'+subAction)(name, val) + except error.RowCreationWanted, why: + self.__manageColumns('create'+subAction, name[len(self.name)+1:]) + self.announceManagementEvent('create'+subAction, name) + except error.RowDestructionWanted, why: + self.__manageColumns('destroy'+subAction, name[len(self.name)+1:]) + self.announceManagementEvent('destroy'+subAction, name) + + def writeTest(self, name, val): self.__delegate('Test', name, val) + def writeCommit(self, name, val): self.__delegate('Commit', name, val) + def writeCleanup(self, name, val): self.__delegate('Cleanup', name, val) + def writeUndo(self, name, val): self.__delegate('Undo', name, val) + + # Table row management + + # Table row access by instance name + + def getInstName(self, colId, instId): + return self.name + (colId,) + instId + + # Table index management + + def getIndicesFromInstId(self, instId): + """Return index values for instance identification""" + indices = [] + for impliedFlag, modName, symName in self.indexNames: + mibObj, = mibBuilder.importSymbols(modName, symName) + val = mibObj.getColumnInitializer().syntax + instId = self.setFromName(val, instId, impliedFlag) + indices.append(val.get()) + if instId: + raise error.SmiError( + 'Exsessive instance identifier sub-OIDs left at %s: %s' % + (self, instId) + ) + return tuple(indices) + + def getInstIdFromIndices(self, *indices): + """Return column instance identification from indices""" + idx = 0; instId = () + for impliedFlag, modName, symName in self.indexNames: + mibObj, = mibBuilder.importSymbols(modName, symName) + if idx < len(indices): + instId = instId + self.getAsName( + mibObj.getColumnInitializer().syntax.set(indices[idx]), + impliedFlag + ) + return instId + + # Table access by index + + def getInstNameByIndex(self, colId, *indices): + """Build column instance name from components""" + return self.name + (colId,) + apply( + self.getInstIdFromIndices, indices + ) + + def getInstNamesByIndex(self, *indices): + """Build column instance names from indices""" + instNames = [] + for columnName in self._vars.keys(): + instNames.append( + apply(self.getInstNameByIndex, + (columnName[-1],) + indices) + ) + return tuple(instNames) + +class MibTable(MibTree): + """MIB table. Manages a set of TableRow's""" + +zeroDotZero = ObjectIdentity((0,0)) + +#dot = MibTree() +iso = MibTree((1,)) +org = MibIdentifier(iso.name + (3,)) +dod = MibIdentifier(org.name + (6,)) +internet = MibIdentifier(dod.name + (1,)) +directory = MibIdentifier(internet.name + (1,)) +mgmt = MibIdentifier(internet.name + (2,)) +mib_2 = MibIdentifier(mgmt.name + (1,)); mib_2.label = 'mib-2' +transmission = MibIdentifier(mib_2.name + (10,)) +experimental = MibIdentifier(internet.name + (3,)) +private = MibIdentifier(internet.name + (4,)) +enterprises = MibIdentifier(private.name + (1,)) +security = MibIdentifier(internet.name + (5,)) +snmpV2 = MibIdentifier(internet.name + (6,)) + +snmpDomains = MibIdentifier(snmpV2.name + (1,)) +snmpProxys = MibIdentifier(snmpV2.name +(2,)) +snmpModules = MibIdentifier(snmpV2.name +(3,)) + +mibBuilder.exportSymbols( + 'SNMPv2-SMI', Integer32=Integer32, Bits=Bits, IpAddress=IpAddress, + Counter32=Counter32, Gauge32=Gauge32, Unsigned32=Unsigned32, + TimeTicks=TimeTicks, Opaque=Opaque, Counter64=Counter64, + ExtUTCTime=ExtUTCTime, MibNodeBase=MibNodeBase, + ModuleIdentity=ModuleIdentity, ObjectIdentity=ObjectIdentity, + NotificationType=NotificationType, MibVariable=MibVariable, + MibIdentifier=MibIdentifier, MibTree=MibTree, + MibTableColumn=MibTableColumn, MibTableRow=MibTableRow, + MibTable=MibTable, zeroDotZero=zeroDotZero, + iso=iso, org=org, dod=dod, internet=internet, + directory=directory, mgmt=mgmt, mib_2=mib_2, transmission=transmission, + experimental=experimental, private=private, enterprises=enterprises, + security=security, snmpV2=snmpV2, snmpDomains=snmpDomains, + snmpProxys=snmpProxys, snmpModules=snmpModules + ) + +# XXX +# maybe re-factor tree facilities diff --git a/pysnmp/smi/mibs/SNMPv2-TC.py b/pysnmp/smi/mibs/SNMPv2-TC.py new file mode 100644 index 00000000..28e7708d --- /dev/null +++ b/pysnmp/smi/mibs/SNMPv2-TC.py @@ -0,0 +1,343 @@ +from string import split, digits +from pysnmp.smi import error +from pysnmp.asn1 import subtypes + +OctetString, Integer, ObjectIdentifier = mibBuilder.importSymbols( + 'ASN1', 'OctetString', 'Integer', 'ObjectIdentifier' + ) +TimeTicks, = mibBuilder.importSymbols('SNMPv2-SMI', 'TimeTicks') + +class TextualConvention: + displayHint = '' + status = 'current' + description = '' + reference = '' + bits = () + __integer = Integer() + __octetString = OctetString() + __objectIdentifier = ObjectIdentifier() + def getDisplayHint(self): return self.displayHint + def getStatus(self): return self.status + def getDescription(self): return self.description + def getReference(self): return self.reference + + def prettyGet(self): + """Implements DISPLAY-HINT evaluation""" + if self.displayHint and self.__integer.isSubtype(self): + value = self.get() + t, f = apply(lambda t, f=0: (t, f), split(self.displayHint, '-')) + if t == 'x': + return '0x%x' % value + elif t == 'd': + try: + return '%.*f' % (int(f), float(value)/pow(10, int(f))) + except StandardError, why: + raise error.SmiError( + 'float num evaluation error: %s' % why + ) + elif t == 'o': + return '0%o' % value + elif t == 'b': + v = value; r = ['B'] + while v: + r.insert(0, '%d' % (v&0x01)) + v = v>>1 + return join(r, '') + else: + raise error.SmiError( + 'Unsupported numeric type spec: %s' % t + ) + elif self.displayHint and self.__octetString.isSubtype(self): + r = '' + v = self.get() + d = self.displayHint + while v and d: + # 1 + if d[0] == '*': + repeatIndicator = repeatCount = int(v[0]) + d = d[1:]; v = v[1:] + else: + repeatCount = 1; repeatIndicator = None + + # 2 + octetLength = '' + while d and d[0] in digits: + octetLength = octetLength + d[0] + d = d[1:] + try: + octetLength = int(octetLength) + except StandardError, why: + raise error.SmiError( + 'Bad octet length: %s' % octetLength + ) + if not d: + raise error.SmiError( + 'Short octet length: %s' % self.displayHint + ) + # 3 + displayFormat = d[0] + d = d[1:] + + # 4 + if d and d[0] not in digits and d[0] != '*': + displaySep = d[0] + d = d[1:] + else: + displaySep = '' + + # 5 + if d and displaySep and repeatIndicator is not None: + repeatTerminator = d[0] + displaySep = '' + d = d[1:] + else: + repeatTerminator = None + + while repeatCount: + repeatCount = repeatCount - 1 + if displayFormat == 'a': + r = r + v[:octetLength] + elif displayFormat in ('x', 'd', 'o'): + n = 0L; vv = v[:octetLength] + while vv: + n = n << 8 + try: + n = n | ord(vv) + vv = vv[1:] + except StandardError, why: + raise error.SmiError( + 'Display format eval failure: %s: %s' + % (vv, why) + ) + if displayFormat == 'x': + r = r + '%02x' % n + elif displayFormat == 'o': + r = r + '%03o' % n + else: + r = r + '%d' % n + else: + raise error.SmiError( + 'Unsupported display format char: %s' % \ + displayFormat + ) + if v and repeatTerminator: + r = r + repeatTerminator + v = v[octetLength:] + if v and displaySep: + r = r + displaySep + if not d: + d = self.displayHint +# if d: +# raise error.SmiError( +# 'Unparsed display hint left: %s' % d +# ) + return r + elif self.displayHint and self.__objectIdentifier.isSubtype(self): + return str(self) + else: + return str(self.get()) + +# elif self.bits: +# try: +# return self.bits[value.get()] +# except StandardError, why: +# raise error.SmiError( +# 'Enumeratin resolution failure for %s: %s' % (self, why) +# ) + + def prettySet(self, value): + # XXX + self.set(value) + + # Overload ASN1 value API access methods +# def _iconv(): pass +# def _oconv(): pass +# def set(self, val): pass +# def get(self): pass + +class DisplayString(TextualConvention, OctetString): + subtypeConstraints = OctetString.subtypeConstraints + ( + subtypes.ValueSizeConstraint(0, 255), + ) + displayHint = "255a" + +class PhysAddress(TextualConvention, OctetString): + displayHint = "1x:" + +class MacAddress(TextualConvention, OctetString): + subtypeConstraints = OctetString.subtypeConstraints + ( + subtypes.ValueSizeConstraint(6, 6), + ) + displayHint = "1x:" + +class TruthValue(TextualConvention, Integer): + subtypeConstraints = Integer.subtypeConstraints + ( + subtypes.SingleValueConstraint(1, 2), + ) + namedValues = Integer.namedValues.clone( + ('true', 1), ('false', 2) + ) + +class TestAndIncr(Integer): + subtypeConstraints = Integer.subtypeConstraints + ( + subtypes.ValueRangeConstraint(0, 2147483647), + ) + def set(self, value): + if value != self: + raise error.InconsistentValueError( + 'Old/new values mismatch %s: %s' % value + ) + value = value + 1 + if value > 2147483646: + value = 0 + return Integer.set(self, value) + +class AutonomousType(TextualConvention, ObjectIdentifier): pass +class InstancePointer(TextualConvention,ObjectIdentifier): + status = 'obsolete' +class VariablePointer(TextualConvention, ObjectIdentifier): pass +class RowPointer(TextualConvention, ObjectIdentifier): pass + +class RowStatus(TextualConvention, Integer): + """A special kind of scalar MIB variable responsible for + MIB table row creation/destruction. + """ + subtypeConstraints = Integer.subtypeConstraints + ( + subtypes.SingleValueConstraint(1, 2, 3, 4, 5, 6), + ) + namedValues = Integer.namedValues.clone( + ('active', 1), ('notInService', 2), ('notReady', 3), + ('createAndGo', 4), ('createAndWait', 5), ('destroy', 6) + ) + + # Known row states + stNotExists, stActive, stNotInService, stNotReady, \ + stCreateAndGo, stCreateAndWait, stDestroy = range(7) + # States transition matrix (see RFC-1903) + stateMatrix = { + # (new-state, current-state) -> (error, new-state) + ( stCreateAndGo, stNotExists ): ( + error.RowCreationWanted, stActive + ), + ( stCreateAndGo, stNotReady ): ( + error.InconsistentValueError, stNotReady + ), + ( stCreateAndGo, stNotInService ): ( + error.InconsistentValueError, stNotInService + ), + ( stCreateAndGo, stActive ): ( + error.InconsistentValueError, stActive + ), + # + ( stCreateAndWait, stNotExists ): ( + error.RowCreationWanted, stActive + ), + ( stCreateAndWait, stNotReady ): ( + error.InconsistentValueError, stNotReady + ), + ( stCreateAndWait, stNotInService ): ( + error.InconsistentValueError, stNotInService + ), + ( stCreateAndWait, stActive ): ( + error.InconsistentValueError, stActive + ), + # + ( stActive, stNotExists ): ( + error.InconsistentValueError, stNotExists + ), + ( stActive, stNotReady ): ( + error.InconsistentValueError, stNotReady + ), + ( stActive, stNotInService ): ( + None, stActive + ), + ( stActive, stActive ): ( + None, stActive + ), + # + ( stNotInService, stNotExists ): ( + error.InconsistentValueError, stNotExists + ), + ( stNotInService, stNotReady ): ( + error.InconsistentValueError, stNotReady + ), + ( stNotInService, stNotInService ): ( + None, stNotInService + ), + ( stNotInService, stActive ): ( + None, stActive + ), + # + ( stDestroy, stNotExists ): ( + error.RowDestructionWanted, stNotExists + ), + ( stDestroy, stNotReady ): ( + error.RowDestructionWanted, stNotExists + ), + ( stDestroy, stNotInService ): ( + error.RowDestructionWanted, stNotExists + ), + ( stDestroy, stActive ): ( + error.RowDestructionWanted, stNotExists + ), + # This is used on instantiation + ( stNotExists, stNotExists ): ( + None, stNotExists + ) + } + defaultValue = stNotExists + + def set(self, value): + # Run through states transition matrix, resolve new instance value + err, val = self.stateMatrix.get( + (value.get(), self.get()), + (error.MibVariableError, None) + ) + if err is not None: + err = err( + 'Exception at row state transition %s->%s' % (self, val) + ) + if val is not None: + Integer.set(self, val) + if err is not None: + raise err + return self + +class TimeStamp(TextualConvention, TimeTicks): pass + +class TimeInterval(TextualConvention, Integer): + subtypeConstraints = Integer.subtypeConstraints + ( + subtypes.ValueRangeConstraint(0, 2147483647), + ) + +class DateAndTime(TextualConvention, OctetString): + subtypeConstraints = OctetString.subtypeConstraints + ( + subtypes.ValueSizeConstraint(8, 11), + ) + displayHint = "2d-1d-1d,1d:1d:1d.1d,1a1d:1d" + +class StorageType(TextualConvention, Integer): + subtypeConstraints = Integer.subtypeConstraints + ( + subtypes.SingleValueConstraint(1, 2, 3, 4, 5), + ) + namedValues = Integer.namedValues.clone( + ('other', 1), ('volatile', 2), ('nonVolatile', 3), + ('permanent', 4), ('readOnly', 5) + ) + +class TDomain(TextualConvention, ObjectIdentifier): pass + +class TAddress(TextualConvention, OctetString): + subtypeConstraints = OctetString.subtypeConstraints + ( + subtypes.ValueSizeConstraint(1, 255), + ) + +mibBuilder.exportSymbols( + 'SNMPv2-TC', TextualConvention=TextualConvention, DisplayString=DisplayString, + PhysAddress=PhysAddress, MacAddress=MacAddress, TruthValue=TruthValue, + TestAndIncr=TestAndIncr, AutonomousType=AutonomousType, + InstancePointer=InstancePointer, VariablePointer=VariablePointer, + RowPointer=RowPointer, RowStatus=RowStatus, TimeStamp=TimeStamp, + TimeInterval=TimeInterval, DateAndTime=DateAndTime, StorageType=StorageType, + TDomain=TDomain, TAddress=TAddress + ) diff --git a/pysnmp/smi/mibs/SNMPv2-TM.py b/pysnmp/smi/mibs/SNMPv2-TM.py new file mode 100644 index 00000000..48ea99e8 --- /dev/null +++ b/pysnmp/smi/mibs/SNMPv2-TM.py @@ -0,0 +1,55 @@ +from pysnmp.asn1 import subtypes + +OctetString, = mibBuilder.importSymbols('ASN1', 'OctetString') +ModuleIdentity, MibIdentifier, ObjectIdentity, snmpModules, \ + snmpDomains, snmpProxys = mibBuilder.importSymbols( + 'SNMPv2-SMI', 'ModuleIdentity', 'MibIdentifier', 'ObjectIdentity', + 'snmpModules', 'snmpDomains', 'snmpProxys' + ) +TextualConvention, = mibBuilder.importSymbols('SNMPv2-TC', 'TextualConvention') + +snmpv2tm = ModuleIdentity(snmpModules.name + (19,)) + +snmpUDPDomain = ObjectIdentity(snmpDomains.name + (1,)) + +class SnmpUDPAddress(TextualConvention, OctetString): + subtypeConstraints = OctetString.subtypeConstraints + ( + subtypes.ValueSizeConstraint(6, 6), + ) + displayHint = "1d.1d.1d.1d/2d" + +snmpCLNSDomain = ObjectIdentity(snmpDomains.name + (2,)) +snmpCONSDomain = ObjectIdentity(snmpDomains.name + (3,)) + +class SnmpOSIAddress(TextualConvention, OctetString): + subtypeConstraints = OctetString.subtypeConstraints + ( + subtypes.ValueSizeConstraint(1, 85), + ) + displayHint = "*1x:/1x:" + +snmpDDPDomain = ObjectIdentity(snmpDomains.name + (4,)) + +class SnmpNBPAddress(TextualConvention, OctetString): + subtypeConstraints = OctetString.subtypeConstraints + ( + subtypes.ValueSizeConstraint(3, 99), + ) + +snmpIPXDomain = ObjectIdentity(snmpDomains.name + (5,)) + +class SnmpIPXAddress(TextualConvention, OctetString): + subtypeConstraints = OctetString.subtypeConstraints + ( + subtypes.ValueSizeConstraint(12, 12), + ) + displayHint = "4x.1x:1x:1x:1x:1x:1x.2d" + +rfc1157Proxy = MibIdentifier(snmpProxys.name + (1,)) +rfc1157Domain = MibIdentifier(rfc1157Proxy.name + (1,)) + +mibBuilder.exportSymbols( + 'SNMPv2-TM', snmpv2tm=snmpv2tm, snmpUDPDomain=snmpUDPDomain, + snmpCLNSDomain=snmpCLNSDomain, snmpCONSDomain=snmpCONSDomain, + SnmpOSIAddress=SnmpOSIAddress, snmpDDPDomain=snmpDDPDomain, + SnmpNBPAddress=SnmpNBPAddress, snmpIPXDomain=snmpIPXDomain, + SnmpIPXAddress=SnmpIPXAddress, rfc1157Proxy=rfc1157Proxy, + rfc1157Domain=rfc1157Domain + ) diff --git a/pysnmp/smi/view.py b/pysnmp/smi/view.py new file mode 100644 index 00000000..7a61d661 --- /dev/null +++ b/pysnmp/smi/view.py @@ -0,0 +1,335 @@ +# MIB modules management +from types import ClassType, InstanceType, TupleType +from pysnmp.smi.indices import OrderedDict, OidOrderedDict +from pysnmp.smi import error + +__all__ = [ 'MibViewController' ] + +class MibViewController: + def __init__(self, mibBuilder): + self.mibBuilder = mibBuilder + self.lastBuildId = -1 + + # Indexing part + + def __indexMib(self): + if self.lastBuildId == self.mibBuilder.lastBuildId: + return + + # + # Create indices + # + + # Module name -> module-scope indices + self.__mibSymbolsIdx = OrderedDict() + # Oid <-> label indices + + # Index modules names + for modName in [ '' ] + self.mibBuilder.mibSymbols.keys(): + # Modules index + self.__mibSymbolsIdx[modName] = mibMod = { + 'oidToLabelIdx': OidOrderedDict(), + 'labelToOidIdx': {}, + 'varToNameIdx': {}, + 'typeToModIdx': OrderedDict(), + 'oidToModIdx': {} + } + + if not modName: + globMibMod = mibMod + continue + + # Types & MIB vars indices + for n, v in self.mibBuilder.mibSymbols[modName].items(): + if type(v) == ClassType: + if mibMod['typeToModIdx'].has_key(n): + raise error.SmiError( + 'Duplicate SMI type %s::%s, has %s' % \ + (modName, n, mibMod['typeToModIdx'][n]) + ) + if not globMibMod['typeToModIdx'].has_key(n): + globMibMod['typeToModIdx'][n] = modName + mibMod['typeToModIdx'][n] = modName + elif type(v) == InstanceType: + if mibMod['varToNameIdx'].has_key(n): + raise error.SmiError( + 'Duplicate MIB variable %s::%s has %s' % \ + (modName, n, mibMod['varToNameIdx'][n]) + ) + if not globMibMod['varToNameIdx'].has_key(n): + globMibMod['varToNameIdx'][n] = v.name + mibMod['varToNameIdx'][n] = v.name + if not globMibMod['oidToModIdx'].has_key(v.name): + globMibMod['oidToModIdx'][v.name] = modName + mibMod['oidToModIdx'][v.name] = modName + if not globMibMod['oidToLabelIdx'].has_key(v.name): + globMibMod['oidToLabelIdx'][v.name] = (n, ) + mibMod['oidToLabelIdx'][v.name] = (n, ) +# XXX complain +# raise error.SmiError( +# 'Duplicate MIB variable name %s::%s has %s' % +# (modName, v.name, globMibMod['oidToLabelIdx'][v.name]) +# ) + else: + raise error.SmiError( + 'Unexpected object %s::%s' % (modName, n) + ) + + # Build oid->long-label index + oidToLabelIdx = self.__mibSymbolsIdx['']['oidToLabelIdx'] + labelToOidIdx = self.__mibSymbolsIdx['']['labelToOidIdx'] + if oidToLabelIdx: + prevOid = oidToLabelIdx.keys()[0] + else: + prevOid = () + baseLabel = () + for key in oidToLabelIdx.keys(): + keydiff = len(key) - len(prevOid) + if keydiff > 0: + baseLabel = oidToLabelIdx[prevOid] + if keydiff > 1: + baseLabel = baseLabel + key[-keydiff:-1] + if keydiff < 0: + keyLen = len(key) + i = keyLen-1 + while i: + baseLabel = oidToLabelIdx.get(key[:i]) + if baseLabel: + if i != keyLen-1: + baseLabel = baseLabel + key[i:-1] + break + i = i - 1 + # Build oid->long-label index + oidToLabelIdx[key] = baseLabel + oidToLabelIdx[key] + # Build label->oid index + labelToOidIdx[oidToLabelIdx[key]] = key + prevOid = key + + # Build module-scope oid->long-label index + for mibMod in self.__mibSymbolsIdx.values(): + for oid in mibMod['oidToLabelIdx'].keys(): + mibMod['oidToLabelIdx'][oid] = oidToLabelIdx[oid] + mibMod['labelToOidIdx'][oidToLabelIdx[oid]] = oid + +# for k, v in oidToLabelIdx.items(): print k, v + + self.lastBuildId = self.mibBuilder.lastBuildId + + # Module management + + def getFirstModuleName(self): + self.__indexMib() + modNames = self.__mibSymbolsIdx.keys() + if modNames: + return modNames[0] + raise error.NoSuchModuleError( + 'No modules loaded at %s' % self + ) + + def getNextModuleName(self, modName): + self.__indexMib() + try: + return self.__mibSymbolsIdx.nextKey(modName) + except KeyError: + raise error.NoSuchModuleError( + 'No module next to %s at %s' % (modName, self) + ) + + # MIB tree node management + + def __getOidLabel(self, nodeName, oidToLabelIdx, labelToOidIdx): + """getOidLabel(nodeName) -> (oid, label, suffix)""" + if not nodeName: + return nodeName, nodeName, () + oid = labelToOidIdx.get(nodeName) + if oid: + return oid, nodeName, () + label = oidToLabelIdx.get(nodeName) + if label: + return nodeName, label, () + if len(nodeName) < 2: + return nodeName, nodeName, () + oid, label, suffix = self.__getOidLabel( + nodeName[:-1], oidToLabelIdx, labelToOidIdx + ) + suffix = suffix + nodeName[-1:] + resLabel = label + suffix + resOid = labelToOidIdx.get(resLabel) + if resOid: + return resOid, resLabel, () + resOid = oid + suffix + resLabel = oidToLabelIdx.get(resOid) + if resLabel: + return resOid, resLabel, () + return oid, label, suffix + + def getNodeNameByOid(self, nodeName, modName=''): + self.__indexMib() + mibMod = self.__mibSymbolsIdx.get(modName) + if mibMod is None: + raise error.NoSuchModuleError( + 'No module %s at %s' % (modName, self) + ) + oid, label, suffix = self.__getOidLabel( + nodeName, mibMod['oidToLabelIdx'], mibMod['labelToOidIdx'] + ) + if oid == label: + raise error.NoSuchInstanceError( + 'Can\'t resolve node name %s::%s at %s' % + (modName, nodeName, self) + ) + return oid, label, suffix + + def getNodeNameByDesc(self, nodeName, modName=''): + self.__indexMib() + mibMod = self.__mibSymbolsIdx.get(modName) + if mibMod is None: + raise error.NoSuchModuleError( + 'No module %s at %s' % (modName, self) + ) + oid = mibMod['varToNameIdx'].get(nodeName) + if oid is None: + raise error.NoSuchInstanceError( + 'No such symbol %s::%s at %s' % (modName, nodeName, self) + ) + return self.getNodeNameByOid(oid, modName) + + def getNodeName(self, nodeName, modName=''): + if type(nodeName) == TupleType: + return self.getNodeNameByOid(nodeName, modName) + else: + return self.getNodeNameByDesc(nodeName, modName) + + def getFirstNodeName(self, modName=''): + self.__indexMib() + mibMod = self.__mibSymbolsIdx.get(modName) + if mibMod is None: + raise error.NoSuchModuleError( + 'No module %s at %s' % (modName, self) + ) + if not mibMod['oidToLabelIdx']: + raise error.NoSuchInstanceError( + 'No variables at MIB module %s at %s' % (modName, self) + ) + oid, label = mibMod['oidToLabelIdx'].items()[0] + return oid, label, () + + def getNextNodeName(self, nodeName, modName=''): + oid, label, suffix = self.getNodeName(nodeName, modName) + try: + return self.getNodeName( + self.__mibSymbolsIdx[modName]['oidToLabelIdx'].nextKey(oid) + suffix, + modName + ) + except KeyError: + raise error.NoSuchInstanceError( + 'No name next to %s::%s at %s' % (modName, nodeName, self) + ) + + def getParentNodeName(self, nodeName, modName=''): + oid, label, suffix = self.getNodeName(nodeName, modName) + if len(oid) < 2: + raise error.NoSuchInstanceError( + 'No parent name for %s::%s at %s' % (modName, nodeName, self) + ) + return oid[:-1], label[:-1], oid[-1:] + suffix + + def getNodeLocation(self, nodeName, modName=''): + oid, label, suffix = self.getNodeName(nodeName, modName) + return self.__mibSymbolsIdx['']['oidToModIdx'][oid], label[-1] + + # MIB type management + + def getTypeName(self, typeName, modName=''): + self.__indexMib() + mibMod = self.__mibSymbolsIdx.get(modName) + if mibMod is None: + raise error.NoSuchModuleError( + 'No module %s at %s' % (modName, self) + ) + m = mibMod['typeToModIdx'].get(typeName) + if m is None: + raise error.NoSuchInstanceError( + 'No such type %s::%s at %s' % (modName, typeName, self) + ) + return m, typeName + + def getFirstTypeName(self, modName=''): + self.__indexMib() + mibMod = self.__mibSymbolsIdx.get(modName) + if mibMod is None: + raise error.NoSuchModuleError( + 'No module %s at %s' % (modName, self) + ) + if not mibMod['typeToModIdx']: + raise error.NoSuchInstanceError( + 'No types at MIB module %s at %s' % (modName, self) + ) + t = mibMod['typeToModIdx'].keys()[0] + return mibMod['typeToModIdx'][t], t + + def getNextType(self, typeName, modName=''): + m, t = self.getTypeName(typeName, modName) + try: + return self.__mibSymbolsIdx[m]['typeToModIdx'].nextKey(t) + except KeyError: + raise error.NoSuchInstanceError( + 'No type next to %s::%s at %s' % (modName, typeName, self) + ) + +if __name__ == '__main__': + from pysnmp.smi.builder import MibBuilder + + mibBuilder = MibBuilder().loadModules() + mibView = MibViewController(mibBuilder) +# print mibView.getNodeName('iso') +# print mibView.getNodeName('sysDescr') +# print mibView.getNodeName('sysObjectID', 'SNMPv2-MIB') +# print mibView.getNodeName((1, 3, 6, 1, 2, 1, 1, 3)) + print mibView.getNodeName((1, 3, 6, 1, 2, 1, 1, 'sysContact')) + + print 'MIB tree traversal' + + oid, label, suffix = mibView.getFirstNodeName() + + while 1: + try: + modName, nodeDesc = mibView.getNodeLocation(oid) + print '%s::%s == %s' % (modName, nodeDesc, oid) + oid, label, suffix = mibView.getNextNodeName(oid) + except error.NoSuchInstanceError: + break + + print 'Modules traversal' + modName = mibView.getFirstModuleName() + while 1: + print modName + try: + modName = mibView.getNextModuleName(modName) + except error.NoSuchModuleError: + break + + print 'TEXTUAL-CONVENTION pretty print' + node, = apply( + mibBuilder.importSymbols, mibView.getNodeLocation('snmpEngineID') + ) + print node.syntax.prettyGet() + + print 'Conceptual table indices convertion' + rowNode, = apply( + mibBuilder.importSymbols, mibView.getNodeLocation('snmpCommunityEntry') + ) + print rowNode + entryOid = rowNode.getInstIdFromIndices('router') + print entryOid + print rowNode.getIndicesFromInstId(entryOid) + + +# XXX +# indices -> ../ +# repr node +# how to index ObjectIds at MIB mods? +# how to index mib symbols -- by oid or by Python var name? +# how to handle '-' in symbol names +# implement defs/tc.py to look like a primitive type, SNMP-TC derive from it +# MibTree / MibLoader / MibViewController relations |