1# 2# This file is part of snmpclitools software. 3# 4# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com> 5# License: http://snmplabs.com/snmpclitools/license.html 6# 7import sys 8from pyasn1.type import univ 9from pyasn1.error import PyAsn1Error 10from pysnmp.proto import rfc1902 11from pysnmp import error 12from snmpclitools.cli import base 13 14# Read class 15 16 17def getReadUsage(): 18 return """\ 19Management parameters: 20 [mib-module::]object-name|oid ... 21 mib-module: MIB name (e.g. SNMPv2-MIB) 22 object-name: MIB symbol (e.g. sysDescr.0) or OID 23""" 24 25# Scanner 26 27 28class ReadPduScannerMixIn: 29 pass 30 31# Parser 32 33 34class ReadPduParserMixIn: 35 def p_varBindSpec(self, args): 36 ''' 37 VarBind ::= VarName 38 ''' 39 40 def p_paramsSpec(self, args): 41 ''' 42 Params ::= VarBinds 43 ''' 44 45 def p_pduSpec(self, args): 46 ''' 47 VarBinds ::= VarBind whitespace VarBinds 48 VarBinds ::= VarBind 49 VarBinds ::= 50 VarName ::= ModName semicolon semicolon NodeName 51 VarName ::= ModName semicolon semicolon 52 VarName ::= semicolon semicolon NodeName 53 VarName ::= NodeName 54 ModName ::= string 55 NodeName ::= ObjectName ObjectIndices 56 ObjectName ::= string 57 ObjectIndices ::= ObjectIndex string ObjectIndices 58 ObjectIndices ::= ObjectIndex ObjectIndices 59 ObjectIndices ::= ObjectIndex 60 ObjectIndices ::= 61 ObjectIndex ::= quote string quote 62 ''' 63 64# Generator 65 66 67class __ReadPduGenerator(base.GeneratorTemplate): 68 def n_ModName(self, cbCtx, node): 69 snmpEngine, ctx = cbCtx 70 ctx['modName'] = node[0].attr 71 72 def n_ObjectName(self, cbCtx, node): 73 snmpEngine, ctx = cbCtx 74 objectName = [] 75 for subOid in node[0].attr.split('.'): 76 if not subOid: 77 continue 78 try: 79 objectName.append(int(subOid)) 80 except ValueError: 81 objectName.append(subOid) 82 ctx['objectName'] = tuple(objectName) 83 84 def n_ObjectIndex(self, cbCtx, node): 85 snmpEngine, ctx = cbCtx 86 if 'objectIndices' not in ctx: 87 ctx['objectIndices'] = [] 88 ctx['objectIndices'].append(node[1].attr) 89 90 def n_VarName_exit(self, cbCtx, node): 91 snmpEngine, ctx = cbCtx 92 mibViewCtl = ctx['mibViewController'] 93 if 'modName' in ctx: 94 mibViewCtl.mibBuilder.loadModules(ctx['modName']) 95 if 'objectName' in ctx: 96 objectName = ctx['objectName'] 97 else: 98 objectName = None 99 100 modName = ctx.get('modName', '') 101 102 if objectName: 103 oid, label, suffix = mibViewCtl.getNodeName(objectName, modName) 104 else: 105 oid, label, suffix = mibViewCtl.getFirstNodeName(modName) 106 if sys.version_info[0] < 3: 107 intTypes = (int, long) 108 else: 109 intTypes = (int,) 110 if [x for x in suffix if not isinstance(x, intTypes)]: 111 raise error.PySnmpError( 112 'Cant resolve object at: %s' % (suffix,) 113 ) 114 modName, nodeDesc, _suffix = mibViewCtl.getNodeLocation(oid) 115 mibNode, = mibViewCtl.mibBuilder.importSymbols(modName, nodeDesc) 116 if not hasattr(self, '_MibTableColumn'): 117 self._MibTableColumn, = mibViewCtl.mibBuilder.importSymbols( 118 'SNMPv2-SMI', 'MibTableColumn' 119 ) 120 if isinstance(mibNode, self._MibTableColumn): 121 # Table column 122 if 'objectIndices' in ctx: 123 modName, nodeDesc, _suffix = mibViewCtl.getNodeLocation( 124 mibNode.name[:-1] 125 ) 126 mibNode, = mibViewCtl.mibBuilder.importSymbols( 127 modName, nodeDesc 128 ) 129 suffix = suffix + mibNode.getInstIdFromIndices( 130 *ctx['objectIndices'] 131 ) 132 else: 133 if 'objectIndices' in ctx: 134 raise error.PySnmpError( 135 'Cant resolve indices: %s' % (ctx['objectIndices'],) 136 ) 137 ctx['varName'] = oid + suffix 138 if 'objectName' in ctx: 139 del ctx['objectName'] 140 if 'objectIndices' in ctx: 141 del ctx['objectIndices'] 142 143 def n_VarBind_exit(self, cbCtx, node): 144 snmpEngine, ctx = cbCtx 145 if 'varBinds' not in ctx: 146 ctx['varBinds'] = [(ctx['varName'], None)] 147 else: 148 ctx['varBinds'].append((ctx['varName'], None)) 149 del ctx['varName'] 150 151 def n_VarBinds_exit(self, cbCtx, node): 152 snmpEngine, ctx = cbCtx 153 if 'varBinds' not in ctx or not ctx['varBinds']: 154 ctx['varBinds'] = [((1, 3, 6), None)] 155 156 157def readPduGenerator(cbCtx, ast): 158 __ReadPduGenerator().preorder(cbCtx, ast) 159 160# Write class 161 162 163def getWriteUsage(): 164 return """\ 165Management parameters: 166 <[mib-module::]object-name|oid type| = value> ... 167 mib-module: MIB name (e.g. SNMPv2-MIB) 168 object-name: MIB symbol (e.g. sysDescr.0) or OID 169 type: MIB value type 170 i integer 171 u unsigned integer 172 s string 173 n NULL 174 o ObjectIdentifier 175 t TimeTicks 176 a IP address 177 =: use MIB for value type lookup 178 value: value to write 179""" 180 181# Scanner 182 183WritePduScannerMixIn = ReadPduScannerMixIn 184 185# Parser 186 187 188class WritePduParserMixIn(ReadPduParserMixIn): 189 def p_varBindSpec(self, args): 190 ''' 191 VarBind ::= VarName whitespace VarType whitespace VarValue 192 VarType ::= string 193 VarValue ::= string 194 ''' 195 196# Generator 197 198 199class __WritePduGenerator(__ReadPduGenerator): 200 _typeMap = { 201 'i': rfc1902.Integer(), 202 'u': rfc1902.Integer32(), 203 's': rfc1902.OctetString(), 204 'n': univ.Null(), 205 'o': univ.ObjectIdentifier(), 206 't': rfc1902.TimeTicks(), 207 'a': rfc1902.IpAddress() 208 } 209 210 def n_VarType(self, cbCtx, node): 211 snmpEngine, ctx = cbCtx 212 ctx['varType'] = node[0].attr 213 214 def n_VarValue(self, cbCtx, node): 215 snmpEngine, ctx = cbCtx 216 ctx['varValue'] = node[0].attr 217 218 def n_VarBind_exit(self, cbCtx, node): 219 snmpEngine, ctx = cbCtx 220 mibViewCtl = ctx['mibViewController'] 221 if ctx['varType'] == '=': 222 modName, nodeDesc, suffix = mibViewCtl.getNodeLocation(ctx['varName']) 223 mibNode, = mibViewCtl.mibBuilder.importSymbols(modName, nodeDesc) 224 if hasattr(mibNode, 'syntax'): 225 MibTableColumn, = mibViewCtl.mibBuilder.importSymbols('SNMPv2-SMI', 'MibTableColumn') 226 if isinstance(mibNode, MibTableColumn) or suffix == (0,): 227 val = mibNode.syntax 228 else: 229 raise error.PySnmpError( 230 'Found MIB scalar %s but non-scalar given %s' % 231 (mibNode.name + (0,), ctx['varName']) 232 ) 233 else: 234 raise error.PySnmpError( 235 'Variable %s has no syntax' % (ctx['varName'],) 236 ) 237 else: 238 try: 239 val = self._typeMap[ctx['varType']] 240 except KeyError: 241 raise error.PySnmpError('unsupported SNMP value type "%s"' % ctx['varType']) 242 try: 243 val = val.clone(ctx['varValue']) 244 except PyAsn1Error: 245 raise error.PySnmpError(sys.exc_info()[1]) 246 247 if 'varBinds' not in ctx: 248 ctx['varBinds'] = [(ctx['varName'], val)] 249 else: 250 ctx['varBinds'].append((ctx['varName'], val)) 251 252 253def writePduGenerator(cbCtx, ast): 254 snmpEngine, ctx = cbCtx 255 __WritePduGenerator().preorder((snmpEngine, ctx), ast) 256