Name

global.SnmpIdentityInfoParser

Description

Parses the SNMP - Identity Info MultiProbe result, adding generic NICs and serial numbers to the passed CIData object.

Script

// Discovery
/**
* This class includes the functions to process the snmp identity probes results. 
* Function 'process' parses the 'SNMP - Identity Info' MultiProbe result, adding generic NICs and serial numbers to the passed CIData object.
* Function 'processNetscalerIdentityInfo' parses 'SNMP - Netsclar - Identity Info' Probe result and adds NICs 
*/
var SnmpIdentityInfoParser = Class.create();
SnmpIdentityInfoParser.prototype = {
  
  /**
   * @param CIData ciData The CIData object to append data to.
   */
  initialize: function(ciData) {
  	this.ciData = ciData;
  	// When cisco vlan indexing is turned on, chances are high that the snmp queries for the different
  	// VLANS will return the same serial/NIC info so they need to be deduped before sending to the
  	// Identification Engine or being reconciled by DiscoveryReconciler
  	if (!ciData.serialDeduper)
  		ciData.serialDeduper = {};
  	if (!ciData.nicDeduper)
  		ciData.nicDeduper = {};
  	this.serials = ciData.addRelatedList('cmdb_serial_number', 'cmdb_ci');
  	this.nics = ciData.addRelatedList('cmdb_ci_network_adapter', 'cmdb_ci');
  },
  
  /***********************************************************************************
   * 
   *  The following part is used to parse 'SNMP - Identity Info' MultiProbe result
   *
   ***********************************************************************************/
  
  /**
   * @param string result The XML probe response.
   */
  process: function(result) {
  	var oid_mib2 = 'iso.org.dod.internet.mgmt.mib-2.';
  	var oid_ip   = oid_mib2 + 'ip';
  	var oid_ipv6 = oid_mib2 + 'ipv6MIB.ipv6MIBObjects';
  	
  	var snmp = new SNMPResponse(result);
  	this._processSerialInfo(snmp);
  	
  	var ips   = snmp.getOIDTable(oid_ip, 'ipAddrEntry');
  	var ipv6s = snmp.getOIDTable(oid_ipv6, 'ipv6AddrEntry');
  	var validInterfaces = this._getValidInterfaces(snmp);
  	
  	for (var index in validInterfaces) {
  		var if_entry = validInterfaces[index];
  		var ipAddresses = []; // If there are no IPv4 addresses, then skip the interface...
  		if (!this._findIPv4Addresses(ips, if_entry.index, ipAddresses))			
  			continue;
  		
  		this._findIPv6Addresses(ipv6s, if_entry.index, ipAddresses);        
  		this.addNIC(ipAddresses, if_entry.mac, if_entry.name);
  	}
  },
  
  _findIPv4Addresses: function(ips, interfaceIndex, ipAddresses) {
      var result = false;

      for (var i in ips) {
          var ip_entry = ips[i];
          if (ip_entry['ipAdEntIfIndex'] != interfaceIndex)
              continue;
              
          var ip = ip_entry['ipAdEntAddr'];

          if (ip)
              ip = '' + ip.toString();
  		
          if (!this.isValidNicIP(ip))
              continue;
          
          var mask = ip_entry['ipAdEntNetMask'];       
          if (mask)
              mask = '' + mask.toString();
              
          ipAddresses.push(this._createIpObject(ip, mask,'4'));
          result = true;            
      }
   
      return result;
  },
  
  isValidNicIP: function(ipAddress){
  	if (!SncIPAddressV4.validate(ipAddress))
  		return false;

  	var isInvalid = ipAddress.equals('0.0.0.0') || ipAddress.equals('255.255.255.255') || ipAddress.startsWith('127.');
  	
  	return !isInvalid;
  },

  _findIPv6Addresses: function(ipv6s, interfaceIndex, ipAddresses) {
      for (var i in ipv6s) {
          var ip_entry = ipv6s[i];
          
          var parts = new RegExp("^\.(.+?)\.(.*)$").exec(ip_entry['@instance']);
          if (JSUtil.nil(parts))
              continue;
              
          var nicIndex = parts[1];
          var decimalDottedIPv6 = parts[2];

          if (nicIndex != interfaceIndex)
              continue;
            
          var ip = SncIPAddressV6.getDottedDecimal(decimalDottedIPv6);

          if (!ip || ip.isLocalhost())
              continue;
          
          var mask = ip_entry['ipv6AddrPfxLength'];       
          if (mask)
              mask = '' + mask.toString();
              
          ipAddresses.push(this._createIpObject(ip, mask,'6'));  
      }
  },
  
  _processSerialInfo: function(snmp) {
  	var oid_mib2 = 'iso.org.dod.internet.mgmt.mib-2.';
  	var oid_cisco   = 'iso.org.dod.internet.private.enterprises.cisco.';
  	var oid_foundry = 'iso.org.dod.internet.private.enterprises.foundry.';
  	var oid_apc     = 'iso.org.dod.internet.private.enterprises.apc.';
  	var oid_entity  = oid_mib2 + 'entityMIB.';
  	var oid_printer = oid_mib2 + 'printmib.';
  	
  	// get any serial numbers we might have...
  	// first we look in the entity MIB, as this is the most generic place it might be...
  	var physObjs = snmp.getOIDTable(oid_entity + 'entityMIBObjects.entityPhysical', 'entPhysicalEntry');
  	if(physObjs != null) {
  		for(var instance in physObjs) {
  			if (physObjs[instance]['entPhysicalContainedIn'] === 0 && JSUtil.notNil(physObjs[instance]['entPhysicalSerialNum'])) {
  				this.addSerial('physical', physObjs[instance]['entPhysicalSerialNum']);
  				break;
  			}
  		}
  	}
  	// see if we can find a Cisco serial in the Cisco Stack MIB...
  	this.addSerial('cisco_stack', snmp.getOIDText(oid_cisco + 'workgroup.ciscoStackMIB.chassisGrp.chassisSerialNumberString'));
  	
  	// our last resort for Cisco is their old MIB; note that this value is overwritten by this IOS line:
  	// snmp-server chassis-id xxxx
  	// so we use this only if we have to, as it may be tainted by the touch of humans...
  	this.addSerial('cisco_chassis', snmp.getOIDText(oid_cisco + 'temporary.chassis.chassisId'));
  	
  	// if this wasn't a Cisco device, let's see if it was a Foundry device...
  	this.addSerial('foundry', snmp.getOIDText(oid_foundry + 'products.switch.snChassis.snChasGen.snChasSerNum'));
  	
  	// if this was an APC PDU 
  	this.addSerial('apc_pdu', snmp.getOIDText(oid_apc + 'products.hardware.masterswitch.sPDUIdent.sPDUIdentSerialNumber') );
  	
  	// if there was no serial number otherwise, then maybe we've got a printer here...
  	var printerGen = snmp.getOIDTable(oid_printer + 'prtGeneral', 'prtGeneralEntry');
  	if ((printerGen != null) && (typeof printerGen['1'] != 'undefined'))
  		this.addSerial('printer', printerGen['1']['prtGeneralSerialNumber']);
  	
  	// let's see if we've got an APC UPS here, with its very own serial number...
  	this.addSerial('standard', snmp.getOIDText(oid_apc + 'products.hardware.ups.upsIdent.upsAdvIdent.upsAdvIdentSerialNumber'));
  	
  },
  
  /***********************************************************************************
   * 
   *  The following part is used to parse 'SNMP - Netscaler - Identity Info' Probe result
   *
   ***********************************************************************************/
  
   processNetscalerIdentityInfo: function(result) {
  	 
  	var oid_group = 'iso.org.dod.internet.private.enterprises.netScaler.nsProducts.rs9000.nsSysGroup';
  	var snmp = new SNMPResponse(result);
  	var ips = snmp.getOIDTable(oid_group, 'nsIpAddrEntry');
  	var vlans = snmp.getOIDTable(oid_group,'vlanEntry');
  	
  	var validInterfaces = this._getValidInterfaces(snmp);
  	for (var index in validInterfaces) {
  		var if_entry = validInterfaces[index];
  		var ipAddresses = []; // If there are no IPv4 addresses, then skip the interface...
  		if (!this._findNetscalerIPV4(ips, vlans, if_entry.name, ipAddresses))			
  			continue;
          
  		
  		this.addNIC(ipAddresses, if_entry.mac, if_entry.name);
  	}
  },
  
  /**
   * Netscaler by default does not provide any differentiation between network interfaces. 
   * All network traffic is transmitted on all interfaces.
   * The ip_addresses in nsIpAddrEntry can be assigned to all interfaces. If the ipVlan was 
   * defined for the ip_address then the ip_address will be assigned to only interfaces 
   * assigned to that vlan. 
   */
  _findNetscalerIPV4: function (ips, vlans, interfaceName, ipAddresses) {
  	var result = false;
  	for (var i in ips) {
  		var ip_entry = ips[i];
  		var ip = ip_entry['ipAddr'];
  		if (ip)
  			ip = '' + ip.toString();
  		
  		if (!GlideIPAddressUtil.isValidNicIP(ip))
  				continue;
  		
  		if (!ip_entry['ipVlan']) {
  			ipAddresses.push(this._createIpObject(ip, ip_entry['ipNetmask'], '4'));
  			result = true;
  			continue;
  		}
  		
  		var ipVlan = ip_entry['ipVlan'].toString() + '';
  		
  		// "NA" means Vlan 1 confirmed by Netscaler Supports (PRB1258867)
  		if (ipVlan == 'NA') 
  			ipVlan = '1';
  			
  		for (var vIndex in vlans) {
  			var vlan_entry = vlans[vIndex];
  			var vlan_id = vlan_entry['vlanId'].toString() + '';
  			
  			if ( vlan_id != ipVlan) 
  				continue;
  			
  			var vInterfaces = vlan_entry['vlanMemberInterfaces'];
  			
  			if (!vInterfaces)
  				continue; 
  			
  			vInterfaces = (vInterfaces.toString() + '').trim();
  			var interfaceList = vInterfaces.split(' '); 
  			if (interfaceList.indexOf(interfaceName) != -1) {
  				ipAddresses.push(this._createIpObject(ip_entry['ipAddr'], ip_entry['ipNetmask'],'4'));
  				result = true; 
  			}
  			
  		}
  		
  	}
  	return result; 
  },
  
  
  
  /***********************************************************************************
   * 
   *  Internal functions 
   *
   ***********************************************************************************/

  _createIpObject: function(ip, mask, version) {
  	var ipObj = {};
  	ipObj.ip_address = ip;
  	ipObj.netmask = mask;
  	ipObj.ip_version = version;
  	ipObj.discovery_source = 'ServiceNow';
  	
  	return ipObj;
  },
  
  addNIC: function(ipAddresses, mac, name) {        
      var nic = {};
      nic[ 'name'        ] = name;
      nic[ 'ip_address'  ] = (ipAddresses.length > 0) ? ipAddresses[0].ip_address : null;
      nic[ 'netmask'     ] = (ipAddresses.length > 0) ? ipAddresses[0].netmask : null;
      nic[ 'mac_address' ] = mac ? mac: null;
      nic[ 'ip_addresses'] = ipAddresses;
      nic['discovery_source'] = 'ServiceNow';
      
  	var key = nic.name + ":" + nic.ip_address + ":" + nic.netmask + ":" + nic.mac_address;
  	if (!this.ciData.nicDeduper[key]) {
  		this.nics.addRec(nic);
  		this.ciData.nicDeduper[key] = true;
  	}
  },
  
  addSerial: function(type, serial) { 	
      // just bail out if we don't have anything here...
      if ((serial == null) || (typeof serial == 'undefined') || gs.nil(serial) || !(new SncSerialNumber().isValid(serial)))
          return;
      
      // if this is the first serial we've seen, record it in the base ci...
      var ci_serial = this.ciData.getData()['serial_number'];
      if ((ci_serial == null) || (typeof ci_serial == 'undefined'))
          this.ciData.getData()['serial_number'] = serial;
      
      // and add it to our serial number list...
      var sr = {};
      sr[ 'serial_number_type' ] = type;
      sr[ 'serial_number' ]      = serial;
      sr[ 'valid' ]              = true;
  	
  	var key = sr.serial_number_type + ":" + sr.serial_number;
  	if (!this.ciData.serialDeduper[key]) {
  		this.serials.addRec(sr);
  		this.ciData.serialDeduper[key] = true;
  	}
  },
  
  /**
   * Verify some common conditions for the snmp interfaces
   */
  _getValidInterfaces: function(snmp) {
  	var validInterfaces = {};
  	var oid_mib2    = 'iso.org.dod.internet.mgmt.mib-2.';
  	var oid_interfaces  = oid_mib2 + 'interfaces';
  	var ifs   = snmp.getOIDTable(oid_interfaces, 'ifEntry');
  	for (var index in ifs) {
  		var if_entry = ifs[index];
  
  		// We do not wanna record loopback interface type (http://oid-info.com/get/1.3.6.1.2.1.2.2.1.3)
  		if (if_entry['ifType'] == 24 && !JSUtil.toBoolean(gs.getProperty('glide.discovery.allow_loopback_adapters', false)))
  			continue;
  		
  		/* According to the this article
  		*  http://tools.cisco.com/Support/SNMP/do/BrowseOID.do?local=en&translate=Translate&objectInput=1.3.6.1.2.1.2.2.1.8#oidContent
  		*  The "ifOperStatus" should follow the "ifAdminStatus". However, it's apparent that there are cases where the ifOperStatus is 2 while 
  		*  the ifAdminStatus is 1. Moreoever, there's actually an IP address associated with it. It's only reasonable to assume that ifOperStatus
  		*  is not a reliable way to determine whether a NIC should be recorded.
  		*/		
  		if (if_entry['ifAdminStatus'] != 1)
  			continue;
  			
  		var mac = SncMACAddress.getMACAddressInstance(if_entry['ifPhysAddress']);
  		if (mac)
  			mac = '' + mac.toString();
  		validInterfaces[index] = {};
  		validInterfaces[index].name = if_entry['ifDescr'];
  		validInterfaces[index].index = if_entry['ifIndex'];
  		validInterfaces[index].mac = mac; 
  	}
  	return validInterfaces; 
  	
  },
  

  
  type: 'SnmpIdentityInfoParser'
};

Sys ID

88c548dc37010100dcd48c00dfbe5d2e

Offical Documentation

Official Docs: