summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene M. Kim <astralblue@gmail.com>2017-10-09 04:10:49 -0700
committerIlya Etingof <etingof@gmail.com>2017-10-09 13:10:49 +0200
commit1d5af2afc0b79fd7ed5b7ea9e564932c9adfdaac (patch)
tree840a8ce658f8d1ae17234470f93b4f086262f48e
parentc383f2de5bbdbbd64f880726d7f9a6a55855c82a (diff)
downloadpysnmp-git-1d5af2afc0b79fd7ed5b7ea9e564932c9adfdaac.tar.gz
Render NetworkAddress indices (#87)
* Add OID-index roundtrip methods to NetworkAddress This enables use of NetworkAddress as a table index. * Use NetworkAddress for RFC1213-MIB::atNetAddress Previously atNetAddress defined to be an IpAddress, whose table index mapping was different from that of NetworkAddress. This prevented proper use of RFC1213-MIB::atTable instances, because: - OID-to-symbol resolution was failing; - Symbol-to-OID mapping result was invalid. * Move clone() from Choice to NetworkAddress Previously it was implemented in pyasn1.type.univ.Choice in case there may be more Choice-based types—such as NetworkAddress—used as a table index. However, SMIv2 (RFC 2578) limits the SYNTAX of an OBJECT-TYPE to be only PyASN1 “simple” types, and NetworkAddress is the only known Choice-based type used as a table index in MIB-I, so there is little reason to clutter PyASN1 with the one-off logic in anticipation of something will probably never happen. Having NetworkAddress's own clone() method also allows use of string literals as the value, so the following invocations are all valid: na = NetworkAddress() na1234 = na.clone('1.2.3.4') na1234_2 = na1234.clone() na1234_3 = na.clone(na1234) na4321 = na.clone(IpAddress('4.3.2.1')) To elaborate on simple types, SMIv2 limits the object syntax to be: - a base type (or its refinement) - a textual convention (or its refinement); or - a BITS pseudo-type. All base types descend from ASN.1 integer, octet string, or OID, all of which are simple types. PySNMP defines SMIv2 BITS as a subclass of OctetString, which is again a simple type. Finally, a SMIv2 textual convention (RFC 2579) is simply a syntactic sugar applied on top of either a base type a BITS type, so it is a simple type.
-rw-r--r--pysnmp/proto/rfc1155.py51
-rw-r--r--pysnmp/smi/mibs/RFC1213-MIB.py3
2 files changed, 53 insertions, 1 deletions
diff --git a/pysnmp/proto/rfc1155.py b/pysnmp/proto/rfc1155.py
index fb7e76ae..35f6110b 100644
--- a/pysnmp/proto/rfc1155.py
+++ b/pysnmp/proto/rfc1155.py
@@ -51,6 +51,57 @@ class NetworkAddress(univ.Choice):
namedtype.NamedType('internet', IpAddress())
)
+ def clone(self, value=univ.noValue, **kwargs):
+ """Clone this instance.
+
+ If *value* is specified, use its tag as the component type selector,
+ and itself as the component value.
+
+ :param value: (Optional) the component value.
+ :type value: :py:obj:`pyasn1.type.base.Asn1ItemBase`
+ :return: the cloned instance.
+ :rtype: :py:obj:`pysnmp.proto.rfc1155.NetworkAddress`
+ :raise: :py:obj:`pysnmp.smi.error.SmiError`:
+ if the type of *value* is not allowed for this Choice instance.
+ """
+ cloned = univ.Choice.clone(self, **kwargs)
+ if value is not univ.noValue:
+ # IpAddress is the only supported type, perhaps forever because
+ # this is SNMPv1.
+ if not isinstance(value, IpAddress):
+ value = IpAddress(value)
+ try:
+ tagSet = value.tagSet
+ except AttributeError:
+ raise PyAsn1Error('component value %r has no tag set' % (value,))
+ cloned.setComponentByType(tagSet, value)
+ return cloned
+
+ # RFC 1212, section 4.1.6:
+ #
+ # "(5) NetworkAddress-valued: `n+1' sub-identifiers, where `n'
+ # depends on the kind of address being encoded (the first
+ # sub-identifier indicates the kind of address, value 1
+ # indicates an IpAddress);"
+
+ def cloneFromName(self, value, impliedFlag, parentRow, parentIndices):
+ kind = value[0]
+ clone = self.clone()
+ if kind == 1:
+ clone['internet'] = tuple(value[1:5])
+ return clone, value[5:]
+ else:
+ raise SmiError('unknown NetworkAddress type %r' % (kind,))
+
+ def cloneAsName(self, impliedFlag, parentRow, parentIndices):
+ kind = self.getName()
+ component = self.getComponent()
+ if kind == 'internet':
+ return (1,) + tuple(component.asNumbers())
+ else:
+ raise SmiError('unknown NetworkAddress type %r' % (kind,))
+
+
class Gauge(univ.Integer):
tagSet = univ.Integer.tagSet.tagImplicitly(
diff --git a/pysnmp/smi/mibs/RFC1213-MIB.py b/pysnmp/smi/mibs/RFC1213-MIB.py
index 5dc0d0e2..b0fda664 100644
--- a/pysnmp/smi/mibs/RFC1213-MIB.py
+++ b/pysnmp/smi/mibs/RFC1213-MIB.py
@@ -19,6 +19,7 @@ SingleValueConstraint, ConstraintsIntersection, ValueSizeConstraint, Constraints
ModuleCompliance, NotificationGroup = mibBuilder.importSymbols("SNMPv2-CONF", "ModuleCompliance", "NotificationGroup")
IpAddress, TimeTicks, NotificationType, ModuleIdentity, Integer32, Counter32, MibIdentifier, ObjectIdentity, Gauge32, Unsigned32, mgmt, MibScalar, MibTable, MibTableRow, MibTableColumn, Bits, iso, Counter64, mib_2 = mibBuilder.importSymbols("SNMPv2-SMI", "IpAddress", "TimeTicks", "NotificationType", "ModuleIdentity", "Integer32", "Counter32", "MibIdentifier", "ObjectIdentity", "Gauge32", "Unsigned32", "mgmt", "MibScalar", "MibTable", "MibTableRow", "MibTableColumn", "Bits", "iso", "Counter64","mib-2")
DisplayString, PhysAddress = mibBuilder.importSymbols("SNMPv2-TC", "DisplayString", "PhysAddress")
+from pysnmp.proto.rfc1155 import NetworkAddress
at = MibIdentifier((1, 3, 6, 1, 2, 1, 3))
ip = MibIdentifier((1, 3, 6, 1, 2, 1, 4))
@@ -35,7 +36,7 @@ if mibBuilder.loadTexts: atIfIndex.setDescription("The interface on which this e
atPhysAddress = MibTableColumn((1, 3, 6, 1, 2, 1, 3, 1, 1, 2), PhysAddress()).setMaxAccess("readwrite")
if mibBuilder.loadTexts: atPhysAddress.setStatus('deprecated')
if mibBuilder.loadTexts: atPhysAddress.setDescription("The media-dependent `physical' address. Setting this object to a null string (one of zero length) has the effect of invaliding the corresponding entry in the atTable object. That is, it effectively dissasociates the interface identified with said entry from the mapping identified with said entry. It is an implementation-specific matter as to whether the agent removes an invalidated entry from the table. Accordingly, management stations must be prepared to receive tabular information from agents that corresponds to entries not currently in use. Proper interpretation of such entries requires examination of the relevant atPhysAddress object.")
-atNetAddress = MibTableColumn((1, 3, 6, 1, 2, 1, 3, 1, 1, 3), IpAddress()).setMaxAccess("readwrite")
+atNetAddress = MibTableColumn((1, 3, 6, 1, 2, 1, 3, 1, 1, 3), NetworkAddress()).setMaxAccess("readwrite")
if mibBuilder.loadTexts: atNetAddress.setStatus('deprecated')
if mibBuilder.loadTexts: atNetAddress.setDescription("The NetworkAddress (e.g., the IP address) corresponding to the media-dependent `physical' address.")
ipForwarding = MibScalar((1, 3, 6, 1, 2, 1, 4, 1), Integer32().subtype(subtypeSpec=ConstraintsUnion(SingleValueConstraint(1, 2))).clone(namedValues=NamedValues(("forwarding", 1), ("not-forwarding", 2)))).setMaxAccess("readwrite")