def get_object_type(self, snmp_engine): mib_view = CommandGeneratorVarBinds().getMibViewController( snmpEngine=snmp_engine) object_identity = self._create_object_identity() object_type = ObjectType(object_identity, self.value) object_type.resolveWithMib(mib_view) return object_type
def from_snmp(self, host, community): assert host assert community # switch port names and numbers # 1.3.6.1.2.1.31.1.1.1.1 oid = ObjectType(ObjectIdentity('IF-MIB', 'ifName')) for port_num_raw, port_name in _snmp_walk(host, community, oid): sw_port_num = port_num_raw[port_num_raw.rfind('.') + 1:] self._add_switch_port(sw_port_num, port_name) # mac addresses table # 1.3.6.1.2.1.17.7.1.2.2.1.2 oid = ObjectType(ObjectIdentity('1.3.6.1.2.1.17.7.1.2.2.1.2')) for mac_raw, sw_port_num in _snmp_walk(host, community, oid): name_parts = mac_raw.split('.') mac_address = _normalize_mac("".join( [("%02x" % int(name_parts[x])).upper() for x in range(len(name_parts) - 6, len(name_parts))] )).upper() self._add_server_port(self.get_port_name(sw_port_num), mac_address) # arp address table # 3.6.1.2.1.4.22.1.2 oid = ObjectType(ObjectIdentity('IP-MIB', 'ipNetToMediaPhysAddress')) for ip_addr_raw, mac_addr in _snmp_walk(host, community, oid): mac_addr = _normalize_mac(mac_addr) name_parts = ip_addr_raw.split('.') ip_address = ".".join([name_parts[x] for x in range(len(name_parts) - 4, len(name_parts))]) self._add_server_port_ip(mac_addr, ip_address)
def __init__(self, oid, value, snmp_engine, logger): self._raw_oid = oid self._snmp_mib_translator = CommandGeneratorVarBinds.getMibViewController( snmp_engine) self._logger = logger self._mib_id = None self._mib_name = None self._index = None self._raw_value = value self._object_id = ObjectIdentity(self._raw_oid) self._object_type = ObjectType(self._object_id, self._raw_value)
def f(snmp, portstr): snmp._command( snmp.cmd_gen.setCmd, ObjectType( ObjectIdentity('GEIST-MIB-V3', 'ctrlOutletStatus', int(portstr)), Gauge32(3))) sleep(delay) snmp._command( snmp.cmd_gen.setCmd, ObjectType( ObjectIdentity('GEIST-MIB-V3', 'ctrlOutletStatus', int(portstr)), Gauge32(1)))
def trap(self, work): var_bind_table = [] not_translated_oids = [] remaining_oids = [] oid_values = set() remotemibs = set() metrics = {} for w in work["data"]: if OID_VALIDATOR.match(w[1]): with suppress(Exception): found, mib = self.is_mib_known(w[1], w[1], work["host"]) if found and mib not in oid_values: self.load_mibs([mib]) oid_values.add(mib) try: var_bind_table.append( ObjectType(ObjectIdentity(w[0]), w[1]).resolveWithMib(self.mib_view_controller)) except SmiError: not_translated_oids.append((w[0], w[1])) for oid in not_translated_oids: found, mib = self.is_mib_known(oid[0], oid[0], work["host"]) if found: remotemibs.add(mib) remaining_oids.append((oid[0], oid[1])) if remotemibs: self.load_mibs(remotemibs) for w in remaining_oids: try: var_bind_table.append( ObjectType(ObjectIdentity(w[0]), w[1]).resolveWithMib(self.mib_view_controller)) except SmiError: logger.warning(f"No translation found for {w[0]}") _, _, result = self.process_snmp_data(var_bind_table, metrics, work["host"]) return { "time": time.time(), "result": result, "address": work["host"], "detectchange": False, "sourcetype": "sc4snmp:traps", }
def set(self, oids): """SNMP Set operation. :param oids: list of oids to set. oid can be full dotted OID or (MIB, OID name, [index]). For example, the OID to get sysContact can by any of the following: ('SNMPv2-MIB', 'sysContact', 0) '1.3.6.1.2.1.1.4.0' snmp.set([(("CISCO-CONFIG-COPY-MIB", "ccCopyProtocol", 10), 1), (("CISCO-CONFIG-COPY-MIB", "ccCopySourceFileType", 10), 1), (("CISCO-CONFIG-COPY-MIB", "ccCopyDestFileType", 10), 3), (("CISCO-CONFIG-COPY-MIB", "ccCopyServerAddress", 10), "10.212.95.180"), (("CISCO-CONFIG-COPY-MIB", "ccCopyFileName", 10), "test_snmp_running_config_save"), (("CISCO-CONFIG-COPY-MIB", "ccCopyVrfName", 10), "management"), (("CISCO-CONFIG-COPY-MIB", "ccCopyEntryRowStatus", 10), 4)]) """ if self.is_read_only: raise Exception(self.__class__.__name__, "SNMP Read Community doesn't support snmp set command") object_identities = [] for oid in oids: if type(oid) is list or type(oid) is tuple: oid_0 = list(oid) if len(oid_0) < 2: raise Exception(self.__class__.__name__, "Missing oid or value data") if type(oid[0]) is list or type(oid[0]) is tuple: if (len(oid_0[0])) < 3: raise Exception(self.__class__.__name__, "Missing oid index") object_identities.append(ObjectType(ObjectIdentity(*oid_0[0]), oid[1])) else: raise Exception(self.__class__.__name__, "Wrong oids parameter") self._write_command(self.cmd_gen.setCmd, *object_identities)
def get_security_engine_id(logger, ir: InventoryRecord, snmpEngine: SnmpEngine): observerContext: Dict[Any, Any] = {} transportTarget = UdpTransportTarget((ir.address, ir.port), timeout=UDP_CONNECTION_TIMEOUT) # Register a callback to be invoked at specified execution point of # SNMP Engine and passed local variables at execution point's local scope snmpEngine.observer.registerObserver( lambda e, p, v, c: c.update(securityEngineId=v["securityEngineId"]), "rfc3412.prepareDataElements:internal", cbCtx=observerContext, ) # Send probe SNMP request with invalid credentials authData = UsmUserData("non-existing-user") errorIndication, errorStatus, errorIndex, varBinds = next( getCmd( snmpEngine, authData, transportTarget, ContextData(), ObjectType(ObjectIdentity("SNMPv2-MIB", "sysDescr", 0)), )) # See if our SNMP engine received REPORT PDU containing securityEngineId securityEngineId = fetch_security_engine_id(observerContext, errorIndication) logger.debug(f"securityEngineId={securityEngineId}") return securityEngineId
def snmpRecvCallback(dispatcher, domain, address, msg): logger = logging.getLogger("apctrap") while msg: version = int(api.decodeMessageVersion(msg)) if version in api.protoModules: module = api.protoModules[version] else: logger.error("SYSTEM\tERROR | Unsupported SNMP Version") return req, msg = decoder.decode(msg, asn1Spec=module.Message()) logger.info("NOTIFICATION\t{} | {}".format(address, domain)) pdu = module.apiMessage.getPDU(req) if not pdu.isSameTypeWith(module.TrapPDU()): continue if version == api.protoVersion1: varBinds = module.apiTrapPDU.getVarBindList(pdu) else: varBinds = module.apiPDU.getVarBindList(pdu) for v, b in varBinds: key = '.'.join([str(i) for i in v._value]) value = b.getComponent('simple')._value parsed = ObjectType(ObjectIdentity(key), value) try: parsed.resolveWithMib(viewController) except Exception as e: logger.warning( "TRAP\tERROR | Failed to resolve symbol ({}={})".format( key, value)) continue key, value = parsed.prettyPrint().split(" = ") logger.info("TRAP\t{} | {}".format(key, value)) if key == "PowerNet-MIB::mtrapargsString.0": message = value for contact in contacts['contacts']: phoneNumber = contact['phoneNumber'] _redis.publish( 'sms', json.dumps( dict(phoneNumber=phoneNumber, message=message))) return msg
def snmpRecvCallback(dispatcher, domain, address, msg): logger=logging.getLogger("apctrap") while msg: version=int(api.decodeMessageVersion(msg)) if version in api.protoModules: module=api.protoModules[version] else: logger.error("SYSTEM\tERROR | Unsupported SNMP Version") return req,msg=decoder.decode(msg, asn1Spec=module.Message()) logger.info("NOTIFICATION\t{} | {}".format(address, domain)) pdu=module.apiMessage.getPDU(req) if not pdu.isSameTypeWith(module.TrapPDU()): continue if version==api.protoVersion1: varBinds=module.apiTrapPDU.getVarBindList(pdu) else: varBinds=module.apiPDU.getVarBindList(pdu) for v,b in varBinds: key='.'.join([str(i) for i in v._value]) value=b.getComponent('simple')._value parsed=ObjectType(ObjectIdentity(key), value) try: parsed.resolveWithMib(viewController) except Exception as e: logger.warning("TRAP\tERROR | Failed to resolve symbol ({}={})".format(key,value)) continue key,value=parsed.prettyPrint().split(" = ") logger.info("TRAP\t{} | {}".format(key,value)) if key=="PowerNet-MIB::mtrapargsString.0": message=value for contact in contacts['contacts']: phoneNumber=contact['phoneNumber'] _redis.publish('sms', json.dumps(dict(phoneNumber=phoneNumber, message=message))) return msg
def from_snmp(self, host, community): assert host assert community # load port id map oid = ObjectType(ObjectIdentity('1.3.6.1.2.1.17.1.4.1.2')) for name, value in _snmp_walk(host, community, oid): self.snmpid__port_num__map[value] = name.split('.')[-1] # switch port names and numbers oid = ObjectType(ObjectIdentity('1.3.6.1.2.1.31.1.1.1.1')) for name, value in _snmp_walk(host, community, oid): snmp_port_id = name.split('.')[-1] if snmp_port_id in self.snmpid__port_num__map: real_port_number = self.snmpid__port_num__map[snmp_port_id] self._add_switch_port(real_port_number, value) else: logger.warning("There is no mapping for the SNMP port ID: %s" % snmp_port_id) # mac addresses table oid = ObjectType(ObjectIdentity('1.3.6.1.2.1.17.7.1.2.2.1.2')) for name, value in _snmp_walk(host, community, oid): name_parts = name.split('.') mac_address = "".join([ ("%02x" % int(name_parts[x])).upper() for x in range(len(name_parts) - 6, len(name_parts)) ]).upper() self._add_server_port(self.get_port_name(value), mac_address) # arp address table oid = ObjectType(ObjectIdentity('IP-MIB', 'ipNetToMediaPhysAddress')) for name, value in _snmp_walk(host, community, oid): ip_address = '.'.join(name.split('.')[-4:]) self._add_server_port_ip(value.upper(), ip_address)
def _fetch_data(pipeline_: Pipeline): snmp_version = 0 if pipeline_.source.version == 'v1' else 1 for host in pipeline_.source.hosts: host_ = host if '://' in host else f'//{host}' url = urlparse(host_) iterator = getCmd(SnmpEngine(), CommunityData(pipeline_.source.read_community, mpModel=snmp_version), UdpTransportTarget( (url.hostname, url.port or SNMP_DEFAULT_PORT), timeout=pipeline_.source.query_timeout, retries=0), ContextData(), *[ ObjectType(ObjectIdentity(mib)) for mib in pipeline_.config['oids'] ], lookupNames=True, lookupMib=True) for i in iterator: yield i, host
def validate_connection(self): errors = [] snmp_version = 0 if self.source.version == 'v1' else 1 for host in self.source.hosts: host_ = host if '://' in host else f'//{host}' url = urllib.parse.urlparse(host_) iterator = getCmd( SnmpEngine(), CommunityData(self.source.read_community, mpModel=snmp_version), UdpTransportTarget((url.hostname, url.port or SNMP_DEFAULT_PORT), timeout=10, retries=0), ContextData(), ObjectType(ObjectIdentity('1.3.6.1.2.1.1.5.0')), lookupNames=True, lookupMib=True ) for response in iterator: if type(response[0]).__name__ == 'RequestTimedOut': errors.append(f'Couldn\'t get response from `{host}`: {type(response[0]).__name__}') logging.warning(f'Couldn\'t connect to {host}') if len(errors) == len(self.source.hosts): raise ValidationException(errors)
def get_var_binds(self, address, walk=False, profiles=[], walked_first_time=True): varbinds_bulk = set() varbinds_get = set() get_mapping = {} bulk_mapping = {} if walk and (not walked_first_time or not profiles): varbinds_bulk.add(ObjectType(ObjectIdentity("1.3.6"))) else: needed_mibs = [] required_bulk = {} # First pass we only look at profiles for a full mib walk for profile in profiles: # Its possible a profile is removed on upgrade but schedule doesn't yet know if profile in self.profiles and "varBinds" in self.profiles[ profile]: profile_spec = self.profiles[profile] profile_varbinds = profile_spec["varBinds"] for vb in profile_varbinds: if len(vb) == 1: if vb[0] not in required_bulk: required_bulk[vb[0]] = None if not walk: bulk_mapping[f"{vb[0]}"] = profile if vb[0] not in needed_mibs: needed_mibs.append(vb[0]) for profile in profiles: # Its possible a profile is removed on upgrade but schedule doesn't yet know if profile in self.profiles and "varBinds" in self.profiles[ profile]: profile_spec = self.profiles[profile] profile_varbinds = profile_spec["varBinds"] for vb in profile_varbinds: if len(vb) == 2: if vb[0] not in required_bulk or ( required_bulk[vb[0]] and vb[1] not in required_bulk[vb[0]]): if vb[0] not in required_bulk: required_bulk[vb[0]] = [vb[1]] else: required_bulk[vb[0]].append(vb[1]) if not walk: bulk_mapping[f"{vb[0]}:{vb[1]}"] = profile for mib, entries in required_bulk.items(): if entries is None: varbinds_bulk.add(ObjectType(ObjectIdentity(mib))) else: for entry in entries: varbinds_bulk.add( ObjectType(ObjectIdentity(mib, entry))) for profile in profiles: # Its possible a profile is removed on upgrade but schedule doesn't yet know if profile in self.profiles and "varBinds" in self.profiles[ profile]: profile_spec = self.profiles[profile] profile_varbinds = profile_spec["varBinds"] for vb in profile_varbinds: if len(vb) == 3: if vb[0] not in required_bulk or ( required_bulk[vb[0]] and vb[1] not in required_bulk[vb[0]]): varbinds_get.add( ObjectType( ObjectIdentity(vb[0], vb[1], vb[2]))) if not walk: get_mapping[ f"{vb[0]}:{vb[1]}:{vb[2]}"] = profile self.load_mibs(needed_mibs) logger.debug(f"host={address} varbinds_get={varbinds_get}") logger.debug(f"host={address} get_mapping={get_mapping}") logger.debug(f"host={address} varbinds_bulk={varbinds_bulk}") logger.debug(f"host={address} bulk_mapping={bulk_mapping}") return varbinds_get, get_mapping, varbinds_bulk, bulk_mapping
cmdgen.BulkCommandGenerator().sendVarBinds( snmpEngine, addrName, contextData.contextEngineId, contextData.contextName, nonRepeaters, maxRepetitions, varbinds, __bulkSubTreeCmdcbFun, (lookupMib, deferred, [], oidTuple, oidTupleLen, logValues) ) return deferred engine = SnmpEngine() transportTarget = UdpTransportTarget(transportAddr=('1.2.3.4', 161)) blankContextData = ContextData() dfd = bulkSubTreeCmd( engine, CommunityData('public'), transportTarget, blankContextData, 0, 15, ObjectType(ObjectIdentity('1.3.6.1.2.1')) ) dfd.addCallback(printList) dfd.addErrback(println) dfd.addCallback(lambda _: reactor.stop()) reactor.run()
class SnmpResponse(object): def __init__(self, oid, value, snmp_engine, logger): self._raw_oid = oid self._snmp_mib_translator = CommandGeneratorVarBinds.getMibViewController( snmp_engine) self._logger = logger self._mib_id = None self._mib_name = None self._index = None self._raw_value = value self._object_id = ObjectIdentity(self._raw_oid) self._object_type = ObjectType(self._object_id, self._raw_value) @property def _object_identity(self): if not self._object_id.isFullyResolved(): self._object_id.resolveWithMib(self._snmp_mib_translator) return self._object_id @property def object_type(self): if not self._object_type.isFullyResolved(): self._object_type.resolveWithMib(self._snmp_mib_translator) return self._object_type @property def raw_value(self): return self._raw_value @property def oid(self): return self._object_identity.getOid() @property def mib_name(self): if not self._mib_name: self._get_oid() return self._mib_name @property def mib_id(self): if not self._mib_id: self._get_oid() return self._mib_id @property def index(self): if not self._index: self._get_oid() return self._index @property def safe_value(self): result = "" try: result = self.value or "" except TranslateSNMPException: pass return result @property def value(self): try: if self._raw_value is None or not self.object_type: return if hasattr(self.object_type[1], "prettyPrint"): value = self.object_type[1].prettyPrint() else: value = str(self.object_type[1]) if value.lower().startswith("0x"): value = str(self._raw_value) return value except (PySnmpError, SmiError): raise TranslateSNMPException("Error parsing snmp response") def _get_oid(self): oid = self._object_identity.getMibSymbol() self._mib_name = oid[0] self._mib_id = oid[1] if isinstance(oid[-1], tuple): self._index = ".".join(map(lambda x: x.prettyPrint(), oid[-1])) def __str__(self): return self.safe_value def __repr__(self): return self.__str__()
def set(self, object_identity, value): """ Sets the value at object_identity""" # TODO This should not use the internal _command function handler = self._handler('set') return handler._command(handler.cmd_gen.setCmd, ObjectType(object_identity, value))
def get(self, object_identity): handler = self._get_handler('get') return handler.get(ObjectType(object_identity))
def set(self, object_identity, value): handler = self._get_handler('set') return handler._command(handler.cmd_gen.setCmd, ObjectType(object_identity, value))