def _error_check(self, rsp): """Check a decoded response structure for agent errors or exceptions, and raise Python exceptions accordingly.""" if rsp['error_status']: error_index = rsp['error_index']-1 error_oid = asn1.decode(rsp['encoded_oids'][error_index])[0] error_value = asn1.decode(rsp['encoded_oids'][error_index])[0] if rsp['error_status'] == 2: raise NoSuchObjectError(error_oid()) else: raise AgentError("Error code %s at index %s (%s, %s)" % \ (rsp['error_status'], rsp['error_index'], error_oid, error_value)) rsp_oids = [asn1.decode(o)[0] for o in rsp['encoded_oids']] rsp_values = [asn1.decode(v)[0] for v in rsp['encoded_vals']] for rsp_oid, rsp_value in zip(rsp_oids, rsp_values): if isinstance(rsp_value, (asn1.noSuchObject, asn1.noSuchInstance)): raise NoSuchObjectError(rsp_oid) elif isinstance(rsp_value, asn1.endOfMibView): raise EndOfMibViewError(rsp_oid())
def _error_check(self, rsp): """Check a decoded response structure for agent errors or exceptions, and raise Python exceptions accordingly.""" # Check for remote SNMP agent failure (v1) if rsp['error_status']: error_index = rsp['error_index'] - 1 error_oid = asn1.decode(rsp['encoded_oids'][error_index])[0] error_value = asn1.decode(rsp['encoded_oids'][error_index])[0] # Error status 2 means noSuchName (i.e. the OID asked for # doesn't exist in the agent's MIB view) if rsp['error_status'] == 2: raise NoSuchObjectError(error_oid()) else: raise AgentError("Error code %s at index %s (%s, %s)" % (rsp['error_status'], rsp['error_index'], error_oid, error_value)) rsp_oids = [asn1.decode(o)[0] for o in rsp['encoded_oids']] rsp_values = [asn1.decode(v)[0] for v in rsp['encoded_vals']] for rsp_oid, rsp_value in zip(rsp_oids, rsp_values): # Check for SNMP v2c agent exceptions if isinstance(rsp_value, (asn1.noSuchObject, asn1.noSuchInstance)): raise NoSuchObjectError(rsp_oid) elif isinstance(rsp_value, asn1.endOfMibView): raise EndOfMibViewError(rsp_oid())
def _error_check(self, rsp): """Check a decoded response structure for agent errors or exceptions, and raise Python exceptions accordingly.""" # Check for remote SNMP agent failure (v1) if rsp['error_status']: error_index = rsp['error_index']-1 error_oid = asn1.decode(rsp['encoded_oids'][error_index])[0] error_value = asn1.decode(rsp['encoded_oids'][error_index])[0] # Error status 2 means noSuchName (i.e. the OID asked for # doesn't exist in the agent's MIB view) if rsp['error_status'] == 2: raise NoSuchObjectError(error_oid()) else: raise AgentError("Error code %s at index %s (%s, %s)" % ( rsp['error_status'], rsp['error_index'], error_oid, error_value)) rsp_oids = [asn1.decode(o)[0] for o in rsp['encoded_oids']] rsp_values = [asn1.decode(v)[0] for v in rsp['encoded_vals']] for rsp_oid, rsp_value in zip(rsp_oids, rsp_values): # Check for SNMP v2c agent exceptions if isinstance(rsp_value, (asn1.noSuchObject, asn1.noSuchInstance)): raise NoSuchObjectError(rsp_oid) elif isinstance(rsp_value, asn1.endOfMibView): raise EndOfMibViewError(rsp_oid())
def _error_check(self, rsp): """Check a decoded response structure for agent errors or exceptions, and raise Python exceptions accordingly.""" if rsp['error_status']: error_index = rsp['error_index'] - 1 error_oid = asn1.decode(rsp['encoded_oids'][error_index])[0] error_value = asn1.decode(rsp['encoded_oids'][error_index])[0] if rsp['error_status'] == 2: raise NoSuchObjectError(error_oid()) else: raise AgentError("Error code %s at index %s (%s, %s)" % \ (rsp['error_status'], rsp['error_index'], error_oid, error_value)) rsp_oids = [asn1.decode(o)[0] for o in rsp['encoded_oids']] rsp_values = [asn1.decode(v)[0] for v in rsp['encoded_vals']] for rsp_oid, rsp_value in zip(rsp_oids, rsp_values): if isinstance(rsp_value, (asn1.noSuchObject, asn1.noSuchInstance)): raise NoSuchObjectError(rsp_oid) elif isinstance(rsp_value, asn1.endOfMibView): raise EndOfMibViewError(rsp_oid())
def get(self, query="1.3.6.1.2.1.1.1.0"): """ Does snmpget query on the host. query: OID to use in the query returns the result as a string. """ if not query.startswith("."): query = "." + query # Choose protocol version specific module try: snmp = eval('v' + self.version) except (NameError, AttributeError): raise UnsupportedSnmpVersionError(self.version) objectid = asn1.OBJECTID() oid = objectid.encode(query) # Create SNMP GET request req = snmp.GETREQUEST() req['community'] = self.community req['encoded_oids'] = [oid] # Create SNMP response message framework rsp = snmp.RESPONSE() # Encode SNMP request message and try to send it to SNMP agent and # receive a response try: (answer, _src) = self.handle.send_and_receive(req.encode(), dst=(self.host, self.port)) except role.NoResponse as err: raise TimeOutException(err) except role.NetworkError as err: raise NetworkError(err) # Decode raw response/answer rsp.decode(answer) # Check for errors in the response self._error_check(rsp) # Fetch the value from the response rsp_value = asn1.decode(rsp['encoded_vals'][0])[0] # Return the value as a proper Python type: return rsp_value()
def bulkwalk(self, query="1.3.6.1.2.1.1.1.0", strip_prefix=False): """ Performs an SNMP walk on the host, using GETBULK requests. Will raise an UnsupportedSnmpVersionError if the current version is anything other than 2c. query: OID to use in the query strip_prefix: If True, strips the query OID prefix from the response OIDs. returns an array containing key-value-pairs, where the returned OID is the key. """ if str(self.version) != "2c": raise UnsupportedSnmpVersionError( "Cannot use BULKGET in SNMP version " + self.version) if not query.startswith("."): query = "." + query # Choose protocol version specific module snmp = v2c result = [] root_oid = asn1.OBJECTID() root_oid.encode(query) # Create SNMP GETNEXT request req = snmp.GETBULKREQUEST() req['community'] = self.community req['encoded_oids'] = [root_oid.encode()] req['max_repetitions'] = 256 # Create a response message framework rsp = snmp.RESPONSE() current_oid = root_oid # Traverse agent MIB while 1: # Encode SNMP request message and try to send it to SNMP agent and # receive a response try: (answer, _src) = self.handle.send_and_receive(req.encode(), dst=(self.host, self.port)) except role.NoResponse as err: raise TimeOutException(err) except role.NetworkError as err: raise NetworkError(err) # Decode raw response/answer rsp.decode(answer) # Check for errors in the response try: self._error_check(rsp) except EndOfMibViewError: # Since we are retrieving multiple values, this SNMP # exception must be handled in the loop below instead pass last_response_oid = None for encoded_oid, encoded_val in \ zip(rsp['encoded_oids'], rsp['encoded_vals']): rsp_oid = asn1.decode(encoded_oid)[0] rsp_value = asn1.decode(encoded_val)[0] # Check for reasons to stop walking if isinstance(rsp_value, asn1.endOfMibView): # Nothing more to see here, move along return result if not root_oid.isaprefix(rsp_oid()): # If the current value came from outside the tree we # are traversing, get the hell out of here, we're done # walking the subtree. return result elif rsp_oid == current_oid: # If the GETNEXT response contains the same object # ID as the request, something has gone wrong, and # we didn't see it further up. Just return # whatever results we got. return result else: oid = rsp_oid() if strip_prefix: oid = oid[len(query) + 1:] result.append((oid, rsp_value())) last_response_oid = rsp_oid # Update request ID req['request_id'] += 1 # Load the next request with the last OID received in the # last response req['encoded_oids'] = rsp['encoded_oids'][-1:] current_oid = last_response_oid
def walk(self, query="1.3.6.1.2.1.1.1.0"): """ Does snmpwalk on the host. query: OID to use in the query returns an array containing key-value-pairs, where the returned OID is the key. """ if not query.startswith("."): query = "." + query # Choose protocol version specific module try: snmp = eval('v' + self.version) except (NameError, AttributeError): raise UnsupportedSnmpVersionError(self.version) result = [] root_oid = asn1.OBJECTID() root_oid.encode(query) # Create SNMP GETNEXT request req = snmp.GETNEXTREQUEST() req['community'] = self.community req['encoded_oids'] = [root_oid.encode()] # Create a response message framework rsp = snmp.RESPONSE() current_oid = root_oid # Traverse agent MIB while 1: # Encode SNMP request message and try to send it to SNMP agent and # receive a response try: (answer, _src) = self.handle.send_and_receive(req.encode(), dst=(self.host, self.port)) except role.NoResponse as err: raise TimeOutException(err) except role.NetworkError as err: raise NetworkError(err) # Decode raw response/answer rsp.decode(answer) # Check for errors in the response try: self._error_check(rsp) except EndOfMibViewError: # We just fell off the face of the earth (or walked outside the # agent's MIB view). Return whatever results we got. return result # Fetch the (first) Object ID and value pair from the response, # (there shouldn't be more than one pair) rsp_oid = asn1.decode(rsp['encoded_oids'][0])[0] rsp_value = asn1.decode(rsp['encoded_vals'][0])[0] # Check for reasons to stop walking if not root_oid.isaprefix(rsp_oid()): # If the current GETNEXT response came from outside the # tree we are traversing, get the hell out of here, we're # done walking the subtree. return result elif rsp_oid == current_oid: # If the GETNEXT response contains the same object ID as the # request, something has gone wrong, and we didn't see it # further up. Just return whatever results we got. return result else: result.append((rsp_oid(), rsp_value())) # Update request ID req['request_id'] += 1 # Load the next request with the OID received in the last response req['encoded_oids'] = rsp['encoded_oids'] current_oid = rsp_oid
(answer, src) = self.handle.send_and_receive(req.encode(), dst=(self.host, self.port)) except role.NoResponse, e: raise TimeOutException(e) except role.NetworkError, n: raise NetworkError(n) # Decode raw response/answer rsp.decode(answer) # Check for errors in the response self._error_check(rsp) # Fetch the value from the response rsp_value = asn1.decode(rsp['encoded_vals'][0])[0] # Return the value as a proper Python type: return rsp_value() def set(self, query, type, value): """ Does snmpset query on the host. query: oid to use in snmpset type: type of value to set. This may be i: INTEGER u: unsigned INTEGER t: TIMETICKS a: IPADDRESS o: OBJID s: OCTETSTRING
(answer, src) = self.handle.send_and_receive( req.encode(), dst=(self.host, self.port)) except role.NoResponse, e: raise TimeOutException(e) except role.NetworkError, n: raise NetworkError(n) # Decode raw response/answer rsp.decode(answer) # Check for errors in the response self._error_check(rsp) # Fetch the value from the response rsp_value = asn1.decode(rsp['encoded_vals'][0])[0] # Return the value as a proper Python type: return rsp_value() def set(self, query, type, value): """ Does snmpset query on the host. query: oid to use in snmpset type: type of value to set. This may be i: INTEGER u: unsigned INTEGER t: TIMETICKS a: IPADDRESS o: OBJID
class Snmp: def __init__(self, host, community="public", version="2c", port=161, retries=3, timeout=1): self.host = host self.community = community self.version = version self.port = port self.retries = retries self.timeout = timeout self.handle = role.manager((host, port)) def getValue(self, query): req = v2c.GETREQUEST() rsp = v2c.RESPONSE() req['encoded_oids'] = [asn1.OBJECTID().encode(query)] req['community'] = self.community (answer, src) = self.handle.send_and_receive(req.encode()) rsp.decode(answer) if req != rsp: raise 'Unmatched response: %s vs %s' % (str(req), str(rsp)) oids = map(lambda x: x[0], map(asn1.OBJECTID().decode, rsp['encoded_oids'])) vals = map(lambda x: x[0](), map(asn1.decode, rsp['encoded_vals'])) if rsp['error_status']: raise 'SNMP error #' + str(rsp['error_status']) + ' for OID #' \ + str(rsp['error_index']) #for (oid, val) in map(None, oids, vals): # print oid + ' ---> ' + str(val) return vals[0] def _error_check(self, rsp): """Check a decoded response structure for agent errors or exceptions, and raise Python exceptions accordingly.""" if rsp['error_status']: error_index = rsp['error_index'] - 1 error_oid = asn1.decode(rsp['encoded_oids'][error_index])[0] error_value = asn1.decode(rsp['encoded_oids'][error_index])[0] if rsp['error_status'] == 2: raise NoSuchObjectError(error_oid()) else: raise AgentError("Error code %s at index %s (%s, %s)" % \ (rsp['error_status'], rsp['error_index'], error_oid, error_value)) rsp_oids = [asn1.decode(o)[0] for o in rsp['encoded_oids']] rsp_values = [asn1.decode(v)[0] for v in rsp['encoded_vals']] for rsp_oid, rsp_value in zip(rsp_oids, rsp_values): if isinstance(rsp_value, (asn1.noSuchObject, asn1.noSuchInstance)): raise NoSuchObjectError(rsp_oid) elif isinstance(rsp_value, asn1.endOfMibView): raise EndOfMibViewError(rsp_oid()) def walk(self, query=".1.3.6.1.2.1.2.2.1.2"): """ Methode pour parcourir la MIB. """ if not query.startswith("."): query = "." + query snmp = self.version result = [] monOid = asn1.OBJECTID() monOid.encode(query) req = v2c.GETNEXTREQUEST() req['community'] = self.community req['encoded_oids'] = [monOid.encode()] rsp = v2c.RESPONSE() current_oid = monOid while 1: try: (answer, src) = self.handle.send_and_receive(req.encode()) except role.NoResponse, e: raise TimeOutException(e) except role.NetworkError, n: raise NetworkError(n) rsp.decode(answer) try: self._error_check(rsp) except EndOfMibViewError: return result rsp_oid = asn1.decode(rsp['encoded_oids'][0])[0] rsp_value = asn1.decode(rsp['encoded_vals'][0])[0] if not monOid.isaprefix(rsp_oid()): return result elif rsp_oid == current_oid: return result else: result.append((rsp_oid(), str(rsp_value()))) req['request_id'] += 1 req['encoded_oids'] = rsp['encoded_oids'] current_oid = rsp_oid