1#!/usr/bin/env python 2# 3# This file is part of snmpclitools software. 4# 5# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com> 6# License: http://snmplabs.com/snmpclitools/license.html 7# 8# Command-line MIB browser 9# 10import sys 11import traceback 12from pysnmp.entity import engine 13from snmpclitools.cli import main, pdu, mibview, base 14from pysnmp.smi.error import NoSuchObjectError 15from pysnmp import error 16from pyasn1.type import univ 17 18 19def getUsage(): 20 return "Usage: %s [OPTIONS] <PARAMETERS>\n\ 21%s%s\ 22TRANSLATE options:\n\ 23 -T TRANSOPTS Set various options controlling report produced:\n\ 24 d: print full details of the given OID\n\ 25 a: dump the loaded MIB in a trivial form\n\ 26 l: enable labeled OID report\n\ 27 o: enable OID report\n\ 28 s: enable dotted symbolic report\n\ 29%s\n" % (sys.argv[0], 30 main.getUsage(), 31 mibview.getUsage(), 32 pdu.getReadUsage()) 33 34# Construct c/l interpreter for this app 35 36 37class Scanner(mibview.MibViewScannerMixIn, 38 pdu.ReadPduScannerMixIn, 39 main.MainScannerMixIn, 40 base.ScannerTemplate): 41 def t_transopts(self, s): 42 r' -T ' 43 self.rv.append(base.ConfigToken('transopts')) 44 45 46class Parser(mibview.MibViewParserMixIn, 47 pdu.ReadPduParserMixIn, 48 main.MainParserMixIn, 49 base.ParserTemplate): 50 def p_transOptions(self, args): 51 ''' 52 Cmdline ::= Options whitespace Params 53 Cmdline ::= Options Params 54 55 Option ::= TranslateOption 56 57 TranslateOption ::= transopts whitespace string 58 TranslateOption ::= transopts string 59 60 ''' 61 62 63class __Generator(base.GeneratorTemplate): 64 def n_TranslateOption(self, cbCtx, node): 65 snmpEngine, ctx = cbCtx 66 mibViewProxy = ctx['mibViewProxy'] 67 if len(node) > 2: 68 opt = node[2].attr 69 else: 70 opt = node[1].attr 71 for c in opt: 72 mibViewProxy.translateMassMode = 1 73 if c == 'd': 74 mibViewProxy.translateFullDetails = 1 75 mibViewProxy.translateMassMode = 0 76 elif c == 'a': 77 mibViewProxy.translateTrivial = 1 78 elif c == 'l': 79 mibViewProxy.translateLabeledOid = 1 80 elif c == 'o': 81 mibViewProxy.translateNumericOid = 1 82 elif c == 's': 83 mibViewProxy.translateSymbolicOid = 1 84 else: 85 raise error.PySnmpError('unsupported sub-option \"%s\"' % c) 86 87 88def generator(cbCtx, ast): 89 snmpEngine, ctx = cbCtx 90 return __Generator().preorder((snmpEngine, ctx), ast) 91 92 93class MibViewProxy(mibview.MibViewProxy): 94 # MIB translate options 95 translateFullDetails = 0 96 translateTrivial = 0 97 translateLabeledOid = 0 98 translateNumericOid = 0 99 translateSymbolicOid = 0 100 101 # Implies SNMPWALK mode 102 translateMassMode = 0 103 104 # Override base class defaults 105 buildEqualSign = 0 106 107 _null = univ.Null() 108 109 def getPrettyOidVal(self, mibViewController, oid, val): 110 prefix, label, suffix = mibViewController.getNodeName(oid) 111 modName, nodeDesc, _suffix = mibViewController.getNodeLocation(prefix) 112 mibNode, = mibViewController.mibBuilder.importSymbols( 113 modName, nodeDesc 114 ) 115 out = '' 116 if self.translateFullDetails: 117 if suffix: 118 out = '%s::%s' % (modName, nodeDesc) 119 out += ' [ %s ]' % '.'.join([str(x) for x in suffix]) 120 out += '\n' 121 else: 122 out += '%s::%s\n%s ::= { %s }' % ( 123 modName, 124 nodeDesc, 125 mibNode.asn1Print(), 126 ' '.join(map(lambda x, y: '%s(%s)' % (y, x), prefix, label)) 127 ) 128 elif self.translateTrivial: 129 out = '%s ::= { %s %s' % ( 130 len(label) > 1 and label[-2] or ".", label[-1], prefix[-1] 131 ) 132 if suffix: 133 out += ' [ %s ]' % '.'.join([str(x) for x in suffix]) 134 out += ' }' 135 elif self.translateLabeledOid: 136 out = '.' + '.'.join( 137 map(lambda x, y: '%s(%s)' % (y, x), prefix, label) 138 ) 139 if suffix: 140 out += ' [ %s ]' % '.'.join([str(x) for x in suffix]) 141 elif self.translateNumericOid: 142 out = '.' + '.'.join([str(x) for x in prefix]) 143 if suffix: 144 out += ' [ %s ]' % '.'.join([str(x) for x in suffix]) 145 elif self.translateSymbolicOid: 146 out = '.' + '.'.join(label) 147 if suffix: 148 out += ' [ %s ]' % '.'.join([str(x) for x in suffix]) 149 if not out: 150 out = mibview.MibViewProxy.getPrettyOidVal( 151 self, mibViewController, oid, self._null 152 ) 153 return out 154 155snmpEngine = engine.SnmpEngine() 156 157# Load up MIB texts (DESCRIPTION, etc.) 158mibBuilder = snmpEngine.getMibBuilder() 159mibBuilder.loadTexts = True 160 161ctx = {} 162 163try: 164 # Parse c/l into AST 165 ast = Parser().parse( 166 Scanner().tokenize(' '.join(sys.argv[1:])) 167 ) 168 169 # Apply configuration to SNMP entity 170 main.generator((snmpEngine, ctx), ast) 171 ctx['mibViewProxy'] = MibViewProxy(ctx['mibViewController']) 172 mibview.generator((snmpEngine, ctx), ast) 173 pdu.readPduGenerator((snmpEngine, ctx), ast) 174 generator((snmpEngine, ctx), ast) 175 176except KeyboardInterrupt: 177 sys.stderr.write('Shutting down...\n') 178 179except error.PySnmpError: 180 sys.stderr.write('Error: %s\n%s' % (sys.exc_info()[1], getUsage())) 181 sys.exit(-1) 182 183except Exception: 184 sys.stderr.write('Process terminated: %s\n' % sys.exc_info()[1]) 185 for line in traceback.format_exception(*sys.exc_info()): 186 sys.stderr.write(line.replace('\n', ';')) 187 sys.exit(-1) 188 189ctx['mibViewProxy'].buildValue = 0 # disable value printout 190 191for oid, val in ctx['varBinds']: 192 while 1: 193 if val is None: 194 val = univ.Null() 195 sys.stdout.write( 196 '%s\n' % ctx['mibViewProxy'].getPrettyOidVal( 197 ctx['mibViewController'], oid, val 198 ) 199 ) 200 if not ctx['mibViewProxy'].translateMassMode: 201 break 202 try: 203 oid, label, suffix = ctx['mibViewController'].getNextNodeName(oid) 204 except NoSuchObjectError: 205 break 206