/// <summary>
        /// Constructs for the given lower layer.
        /// </summary>
        /// <param name="lowerLayer">The lower layer for talking to this device.</param>
        /// <param name="oidLookup">The OID lookup table for the device.</param>
        /// <param name="osVersion">The SW version of the device.</param>
        /// <param name="model">The device's model name. Shall be the same name as used for the device name during OID database lookups.</param>
        /// <param name="options">The options to use.</param>
        public DeviceHandlerBase(ISnmpLowerLayer lowerLayer, IDeviceSpecificOidLookup oidLookup, SemVersion.SemanticVersion osVersion, string model, IQuerierOptions options)
        {
            if (lowerLayer == null)
            {
                throw new ArgumentNullException(nameof(lowerLayer), "lower layer is null when constructing a device handler");
            }

            if (oidLookup == null)
            {
                throw new ArgumentNullException(nameof(oidLookup), "OID lookup table is null when constructing a device handler");
            }

            if (osVersion == null)
            {
                throw new ArgumentNullException(nameof(osVersion), "OS version info is null when constructing a device handler");
            }

            if (string.IsNullOrWhiteSpace(model))
            {
                throw new ArgumentNullException(nameof(model), "Model name is null, empty or white-space-only when constructing a device handler");
            }

            this.LowerLayer = lowerLayer;
            this.OidLookup  = oidLookup;
            this.OsVersion  = osVersion;
            this.Model      = model;
            this.Options    = options ?? throw new ArgumentNullException(nameof(options), "The options are null when constructing a device handler");
        }
Exemple #2
0
        /// <summary>
        /// Construct for a lower layer and a cache data set (from which we return the non-volatile data).
        /// </summary>
        public VolatileFetchingWirelessPeerInfos(IWirelessPeerInfos wirelessPeerInfos, ISnmpLowerLayer lowerLayer)
        {
            this.lowerLayer = lowerLayer ?? throw new System.ArgumentNullException(nameof(lowerLayer), "lower layer is null");
            this.underlyingWirelessPeerInfo = wirelessPeerInfos ?? throw new System.ArgumentNullException(nameof(wirelessPeerInfos), "underlying wireless peer info is null");

            this.Details = wirelessPeerInfos.Details.Select(underlyingPeerInfo => new VolatileFetchingWirelessPeerInfo(underlyingPeerInfo, this.lowerLayer)).ToList();
        }
        /// <summary>
        /// Construct for a lower layer and a cache data set (from which we return the non-volatile data).
        /// </summary>
        public VolatileFetchingInterfaceDetails(IInterfaceDetails interfaceDetails, ISnmpLowerLayer lowerLayer)
        {
            this.lowerLayer = lowerLayer ?? throw new System.ArgumentNullException(nameof(lowerLayer), "lower layer is null");
            this.underlyingInterfaceDetails = interfaceDetails ?? throw new System.ArgumentNullException(nameof(interfaceDetails), "underlying interface details is null");

            this.Details = interfaceDetails.Details.Select(underlyingInterfaceDetail => new VolatileFetchingInterfaceDetail(underlyingInterfaceDetail, this.lowerLayer)).ToList();
        }
        /// <summary>
        /// Gets the device handler of the given handler class name via reflection.
        /// </summary>
        /// <param name="handlerClassName">The class name of the device handler to get.</param>
        /// <param name="lowerLayer">The lower layer for talking to this device.</param>
        /// <param name="oidTable">The OID lookup table for the device.</param>
        /// <param name="osVersion">The SW version of the device.</param>
        /// <param name="model">The device's model name. Shall be the same name as used for the device name during OID database lookups.</param>
        /// <param name="options">The options to use.</param>
        /// <returns>The generated device handler.</returns>
        protected IDeviceHandler GetHandlerViaReflection(string handlerClassName, ISnmpLowerLayer lowerLayer, IDeviceSpecificOidLookup oidTable, SemanticVersion osVersion, string model, IQuerierOptions options)
        {
            var type = Type.GetType($"SnmpAbstraction.{handlerClassName}");

            if (type == null)
            {
                var ex = new HamnetSnmpException($"{lowerLayer.Address} ({model} v {osVersion}): Cannot find a DeviceHandler implementation of name '{handlerClassName}'", lowerLayer.Address?.ToString());
                this.CollectException("Missing handler class name", ex);
                throw ex;
            }

            object myObject = null;

            try
            {
                myObject = Activator.CreateInstance(type, lowerLayer, oidTable, osVersion, model, options);
            }
            catch (Exception ex)
            {
                this.CollectException($"Instantiate handler class '{type.FullName}'", ex);

                throw new HamnetSnmpException($"{lowerLayer.Address} ({model} v {osVersion}): Exception while instantiating DeviceHandler of name '{handlerClassName}': {ex.Message}", ex, lowerLayer.Address?.ToString());
            }

            IDeviceHandler castedHandler = myObject as IDeviceHandler;

            if (castedHandler == null)
            {
                var ex = new HamnetSnmpException($"{lowerLayer.Address} ({model} v {osVersion}): Instantiating DeviceHandler of name '{handlerClassName}' is NOT an IDeviceHandler", lowerLayer.Address?.ToString());
                this.CollectException($"Cast handler class '{type.FullName}' to IDeviceHandler", ex);
                throw ex;
            }

            return(castedHandler);
        }
        /// <summary>
        /// Creates a new querier using the given lower layer and options.
        /// </summary>
        /// <param name="lowerLayer">The IP address of the device to query.</param>
        /// <param name="options">The options for the query.</param>
        /// <returns>An <see cref="IHamnetQuerier" /> that talks to the given address.</returns>
        internal IHamnetQuerier Create(ISnmpLowerLayer lowerLayer, IQuerierOptions options)
        {
            if (lowerLayer == null)
            {
                throw new ArgumentNullException(nameof(lowerLayer), "lowerLayer is null");
            }

            IHamnetQuerier querier = null;

            if (options.EnableCaching)
            {
                querier = new CachingHamnetQuerier(lowerLayer, options);
            }
            else
            {
                var detector = new DeviceDetector(lowerLayer);

                IDeviceHandler handler = detector.Detect(options);

                if (handler == null)
                {
                    var errorInfo = $"Cannot obtain a feasible device handler for device '{lowerLayer.Address}'";
                    log.Error(errorInfo);
                    throw new HamnetSnmpException(errorInfo, lowerLayer.Address?.ToString());
                }

                querier = new HamnetQuerier(handler, lowerLayer.Options);
            }

            return(querier);
        }
        /// <summary>
        /// Queries the given OIDs and returns the value as string or null if the OID is not available.
        /// </summary>
        /// <param name="lowerLayer">The lower layer engine to extend.</param>
        /// <param name="oid">The OID to query.</param>
        /// <param name="what">Descriptive text what is being queried. Used for debug/error output</param>
        /// <param name="encoding">If not null, will try to detect whether the string is a hex string and then use the given encoding to decode it.</param>
        /// <returns>The OID's value as string or null if the OID is not available.</returns>
        public static string QueryAsString(this ISnmpLowerLayer lowerLayer, Oid oid, string what, Encoding encoding = null)
        {
            VbCollection result = lowerLayer.Query(oid);
            var          retVal = result[oid]?.Value?.ToString();

            if (retVal == null)
            {
                log.Warn($"Querying '{what}' from '{lowerLayer.Address}' as string returned null");
            }

            if ((encoding != null) && (retVal.Length > 0))
            {
                bool couldBeHexString = true;
                for (int i = 2; i < retVal.Length; i += 3)
                {
                    if (retVal[i] != ' ')
                    {
                        couldBeHexString = false;
                        break;
                    }
                }

                if (couldBeHexString)
                {
                    retVal = encoding.GetString(retVal.HexStringToByteArray(' '));
                }
            }

            return(retVal);
        }
        /// <inheritdoc />
        public override IDeviceHandler CreateHandler(ISnmpLowerLayer lowerLayer, IQuerierOptions options)
        {
            string osVersionString = null;

            // try #1: In IEEE SNMP tree
            try
            {
                osVersionString = lowerLayer.QueryAsString(OsVersionOid, "MikroTik RouterOS Version String #1");
            }
            catch (SnmpException ex)
            {
                this.CollectException("MtikSnmp: Getting version string", ex);
                osVersionString = null;
            }
            catch (HamnetSnmpException ex)
            {
                this.CollectException("MtikSnmp: Getting version string", ex);
                osVersionString = null;
            }

            // try #2: Withing MikroTik enterprise tree
            if (string.IsNullOrWhiteSpace(osVersionString))
            {
                osVersionString = lowerLayer.QueryAsString(OsVersionOid2, "MikroTik RouterOS Version String #2");
            }

            // Example: "RouterOS 6.45.3 (stable) on RB711-5Hn-MMCX"
            Match match = OsVersionExtractionRegex.Match(osVersionString);

            SemanticVersion osVersion = match.Success ? match.Groups[1].Value.ToSemanticVersion() : null;

            var model = lowerLayer.SystemData.Description.Replace(RouterOsDetectionString, string.Empty).Trim();

            log.Info($"Detected device '{lowerLayer.Address}' as MikroTik '{model}' v '{osVersion}'");

            DeviceVersion            deviceVersion;
            IDeviceSpecificOidLookup oidTable = this.ObtainOidTable(model.Trim(), osVersion, out deviceVersion, lowerLayer.Address);

            if (string.IsNullOrWhiteSpace(deviceVersion.HandlerClassName))
            {
                try
                {
                    return(new MikrotikSnmpDeviceHandler(lowerLayer, oidTable, osVersion, model, options));
                }
                catch (Exception ex)
                {
                    this.CollectException("MtikSnmp: OID table lookup", ex);

                    // we want to catch and nest the exception here as the APIs involved are not able to append the infomration for which
                    // device (i.e. IP address) the exception is for
                    throw new HamnetSnmpException($"Failed to create MikroTik handler for device '{lowerLayer.Address}': {ex.Message}", ex, lowerLayer.Address?.ToString());
                }
            }
            else
            {
                return(this.GetHandlerViaReflection(deviceVersion.HandlerClassName, lowerLayer, oidTable, osVersion, model, options));
            }
        }
Exemple #8
0
        /// <summary>
        /// Construct for the given device address and query duration.
        /// </summary>
        /// <param name="lowerSnmpLayer">The communication layer to use for talking to the device.</param>
        /// <param name="queryDuration">The duration of the query.</param>
        protected LazyHamnetSnmpQuerierResultBase(ISnmpLowerLayer lowerSnmpLayer, TimeSpan queryDuration)
            : this(lowerSnmpLayer, queryDuration, lowerSnmpLayer.SystemData?.DeviceModel)
        {
            if (lowerSnmpLayer == null)
            {
                throw new ArgumentNullException(nameof(lowerSnmpLayer), "The handle to the lower layer interface is null");
            }

            this.LowerSnmpLayer = lowerSnmpLayer;
        }
Exemple #9
0
        /// <summary>
        /// Construct for the given device address and query duration.
        /// </summary>
        /// <param name="lowerSnmpLayer">The communication layer to use for talking to the device.</param>
        /// <param name="queryDuration">The duration of the query.</param>
        /// <param name="deviceModel">The model and version of the device.</param>
        protected LazyHamnetSnmpQuerierResultBase(ISnmpLowerLayer lowerSnmpLayer, TimeSpan queryDuration, string deviceModel)
            : base(lowerSnmpLayer.Address, deviceModel, queryDuration)
        {
            if (lowerSnmpLayer == null)
            {
                throw new ArgumentNullException(nameof(lowerSnmpLayer), "The handle to the lower layer interface is null");
            }

            this.LowerSnmpLayer = lowerSnmpLayer;
        }
Exemple #10
0
 /// <summary>
 /// Construct taking the lower layer to use for lazy-querying the data.
 /// </summary>
 /// <param name="lowerSnmpLayer">The communication layer to use for talking to the device.</param>
 /// <param name="oidLookup">The OID lookup table for the device.</param>
 /// <param name="macAddress">The MAC address of the peer (serves as index in OIDs for MikroTik devices).</param>
 /// <param name="interfaceId">The ID of the interface (i.e. the value to append to interface-specific OIDs).</param>
 /// <param name="isAccessPoint">Value indicating whether the device proving the peer info is an access point or a client.</param>
 /// <param name="numberOfClients">The number of clients that are connected to this AP when in AP mode. null if not an AP or not available.</param>
 public LazyLoadingAlixWirelessPeerInfo(
     ISnmpLowerLayer lowerSnmpLayer,
     IDeviceSpecificOidLookup oidLookup,
     string macAddress,
     int?interfaceId,
     bool?isAccessPoint,
     int?numberOfClients)
     : base(lowerSnmpLayer, oidLookup, macAddress, interfaceId, isAccessPoint, numberOfClients)
 {
 }
        /// <inheritdoc />
        public virtual IDeviceHandler CreateHandler(ISnmpLowerLayer lowerLayer, IQuerierOptions options)
        {
            if (this.circularCreateHandler++ > 1)
            {
                var ex = new InvalidOperationException($"Internal Error: DetectableDevice {this.GetType().Name} seems to neither implement CreateHandler(ISnmpLowerLayer lowerLayer, IQuerierOptions options) nor CreateHandler(IpAddress address, IQuerierOptions options)");
                this.CollectException("CreateHandler(ISnmpLowerLayer, IQuerierOptions) circular call", ex);
                throw ex;
            }

            return(this.CreateHandler(lowerLayer.Address, options));
        }
        /// <summary>
        /// Queries the given OIDs and returns the value as OID or null if the OID is not available.
        /// </summary>
        /// <param name="lowerLayer">The lower layer engine to extend.</param>
        /// <param name="oid">The OID to query.</param>
        /// <param name="what">Descriptive text what is being queried. Used for debug/error output</param>
        /// <returns>The OID's value as OID or null if the OID is not available.</returns>
        public static Oid QueryAsOid(this ISnmpLowerLayer lowerLayer, Oid oid, string what)
        {
            VbCollection result = lowerLayer.Query(oid);
            var          retVal = result[oid]?.Value as Oid;

            if (retVal == null)
            {
                log.Warn($"Querying '{what}' from '{lowerLayer.Address}' as OID returned null");
            }

            return(retVal);
        }
        /// <summary>
        /// Queries the given OIDs and returns the value as string or null if the OID is not available.
        /// </summary>
        /// <param name="lowerLayer">The lower layer engine to extend.</param>
        /// <param name="oid">The OID to query.</param>
        /// <param name="what">Descriptive text what is being queried. Used for debug/error output</param>
        /// <returns>The OID's value as int or <see cref="int.MinValue" /> if the OID is not available.</returns>
        public static int QueryAsInt(this ISnmpLowerLayer lowerLayer, Oid oid, string what)
        {
            VbCollection result = lowerLayer.Query(oid);

            int retVal = int.MinValue;

            if (!(result[oid]?.Value?.TryToInt(out retVal) ?? false))
            {
                log.Warn($"Querying '{what}' from '{lowerLayer.Address}' as string returned null");
            }

            return(retVal);
        }
        /// <summary>
        /// Queries the given OIDs and returns the value as <see cref="TimeSpan" /> or null if the OID is not available.
        /// </summary>
        /// <param name="lowerLayer">The lower layer engine to extend.</param>
        /// <param name="oid">The OID to query.</param>
        /// <param name="what">Descriptive text what is being queried. Used for debug/error output</param>
        /// <returns>The OID's value as <see cref="TimeSpan" /> or null if the OID is not available or cannot be parsed as <see cref="TimeSpan" />.</returns>
        public static TimeSpan?QueryAsTimeSpan(this ISnmpLowerLayer lowerLayer, Oid oid, string what)
        {
            VbCollection result = lowerLayer.Query(oid);
            var          retVal = result[oid]?.Value as TimeTicks;

            if (retVal == null)
            {
                log.Warn($"Querying '{what}' from '{lowerLayer.Address}' as TimeTicks returned null");
                return(null);
            }

            return(TimeSpan.FromMilliseconds(retVal.Milliseconds));
        }
 /// <summary>
 /// Construct taking the lower layer to use for lazy-querying the data.
 /// </summary>
 /// <param name="lowerSnmpLayer">The communication layer to use for talking to the device.</param>
 /// <param name="oidLookup">The OID lookup table for the device.</param>
 /// <param name="macAddress">The MAC address of the peer (serves as index in OIDs for MikroTik devices).</param>
 /// <param name="interfaceId">The ID of the interface (i.e. the value to append to interface-specific OIDs).</param>
 /// <param name="isAccessPoint">Value indicating whether the device proving the peer info is an access point or a client.</param>
 /// <param name="numberOfClients">The number of clients that are connected to this AP when in AP mode. null if not an AP or not available.</param>
 protected LazyLoadingGenericWirelessPeerInfo(
     ISnmpLowerLayer lowerSnmpLayer,
     IDeviceSpecificOidLookup oidLookup,
     string macAddress,
     int?interfaceId,
     bool?isAccessPoint,
     int?numberOfClients)
     : base(lowerSnmpLayer)
 {
     this.OidLookup       = oidLookup;
     this.PeerMac         = macAddress;
     this.InterfaceId     = interfaceId;
     this.IsAccessPoint   = isAccessPoint;
     this.NumberOfClients = numberOfClients;
 }
 /// <summary>
 /// Construct taking the lower layer to use for lazy-querying the data.
 /// </summary>
 /// <param name="lowerSnmpLayer">The communication layer to use for talking to the device.</param>
 /// <param name="oidLookup">The OID lookup table for the device.</param>
 /// <param name="peerIndex">The peer's index (to use in SNMP get).</param>
 /// <param name="numberOfClients">The number of clients that are connected to this AP when in AP mode. null if not an AP or not available.</param>
 public LazyLoadingUbiquitiAirFiberWirelessPeerInfo(
     ISnmpLowerLayer lowerSnmpLayer,
     IDeviceSpecificOidLookup oidLookup,
     int peerIndex,
     int?numberOfClients)
     : base(
         lowerSnmpLayer,
         oidLookup,
         null,
         null, // For UBNT there's no way to find which wireless interface this peer belongs to.
         null,
         numberOfClients)
 {
     this.peerIndex = peerIndex;
 }
 /// <summary>
 /// Construct taking the lower layer to use for lazy-querying the data.
 /// </summary>
 /// <param name="lowerSnmpLayer">The communication layer to use for talking to the device.</param>
 /// <param name="oidLookup">The OID lookup table for the device.</param>
 /// <param name="interfaceId">The interface ID (to use in SNMP get).</param>
 /// <param name="peerWalkCollection">The collection generated by the walk operation that triggered creation of this peer info.</param>
 /// <param name="numberOfClients">The number of clients that are connected to this AP when in AP mode. null if not an AP or not available.</param>
 public LazyLoadingUbiquitiAirOs4WirelessPeerInfo(
     ISnmpLowerLayer lowerSnmpLayer,
     IDeviceSpecificOidLookup oidLookup,
     int interfaceId,
     VbCollection peerWalkCollection,
     int?numberOfClients)
     : base(
         lowerSnmpLayer,
         oidLookup,
         null,
         interfaceId,
         null,
         numberOfClients)
 {
     this.walkCollection = peerWalkCollection;
 }
 /// <summary>
 /// Construct taking the lower layer to use for lazy-querying the data.
 /// </summary>
 /// <param name="lowerSnmpLayer">The communication layer to use for talking to the device.</param>
 /// <param name="oidLookup">The OID lookup table for the device.</param>
 /// <param name="macAddress">The MAC address of the peer (serves as index in OIDs for MikroTik devices).</param>
 /// <param name="peerIndex">The peer's index (to use in SNMP get).</param>
 /// <param name="isAccessPoint">Value indicating whether the device proving the peer info is an access point or a client.</param>
 /// <param name="numberOfClients">The number of clients that are connected to this AP when in AP mode. null if not an AP or not available.</param>
 public LazyLoadingUbiquitiAirOs6plusWirelessPeerInfo(
     ISnmpLowerLayer lowerSnmpLayer,
     IDeviceSpecificOidLookup oidLookup,
     string macAddress,
     int peerIndex,
     bool?isAccessPoint,
     int?numberOfClients)
     : base(
         lowerSnmpLayer,
         oidLookup,
         macAddress,
         null, // For UBNT there's no way to find which wireless interface this peer belongs to.
         isAccessPoint,
         numberOfClients)
 {
     this.peerIndex = peerIndex;
 }
Exemple #19
0
        /// <inheritdoc />
        public override bool IsApplicableSnmp(ISnmpLowerLayer snmpLowerLayer, IQuerierOptions options)
        {
            var description = snmpLowerLayer?.SystemData?.Description;

            if (string.IsNullOrWhiteSpace(description))
            {
                var info = $"Description in system data of device '{snmpLowerLayer.Address}' is null, empty or white-space-only: Assuming the device is not a Ubiquiti device";
                log.Warn(info);
                this.CollectException("UbntSnmp: No device description", new HamnetSnmpException(info));
                return(false);
            }

            if (!description.Contains(PossiblyUbiquitiDetectionDescriptionString))
            {
                var info = $"Description in system data of device '{snmpLowerLayer.Address}' doesn't contain string '{PossiblyUbiquitiDetectionDescriptionString}': Assuming the device is not a Ubiquiti device";
                log.Info(info);
                this.CollectException("UbntSnmp: No UBNT-like string in device description", new HamnetSnmpException(info));
                return(false);
            }

            var ubntManufacturer = snmpLowerLayer?.DoWalk(UbntManufacturerDetectionOid);

            if ((ubntManufacturer == null) || (ubntManufacturer.Count == 0))
            {
                var info = $"UBNT Manufacturer ID string of device '{snmpLowerLayer.Address}' is null or empty: The device could still be AirFiber";
                log.Warn(info);
                this.CollectException("UbntSnmp: No UBNT manufacturer detection OID", new HamnetSnmpException(info));
                return(this.DetectAirFiber(snmpLowerLayer));
            }

            var manufacturer = ubntManufacturer.FirstOrDefault(m => m.Value.ToString().Contains(UbiquitiManufactorerDetectionString));

            if (manufacturer == null)
            {
                var info = $"UBNT Manufacturer ID string of device '{snmpLowerLayer.Address}' doesn't contain string '{UbiquitiManufactorerDetectionString}': Assuming the device is not a Ubiquiti device";
                log.Info(info);
                this.CollectException("UbntSnmp: No UBNT manufacturer", new HamnetSnmpException(info));
                return(false);
            }

            this.detectionId = manufacturer.Oid[manufacturer.Oid.Length - 1];

            log.Info($"Device '{snmpLowerLayer.Address}' seems to be a Ubiquiti device (detection ID {this.detectionId})");

            return(true);
        }
        /// <summary>
        /// Constructs for the given lower layer.
        /// </summary>
        /// <param name="lowerLayer">The lower layer for talking to this device.</param>
        /// <param name="oidLookup">The OID lookup table for the device.</param>
        /// <param name="osVersion">The SW version of the device.</param>
        /// <param name="model">The device's model name. Shall be the same name as used for the device name during OID database lookups.</param>
        /// <param name="options">The options to use.</param>
        public AlixDeviceHandler(ISnmpLowerLayer lowerLayer, IDeviceSpecificOidLookup oidLookup, SemanticVersion osVersion, string model, IQuerierOptions options)
            : base(lowerLayer, oidLookup, osVersion, model, options)
        {
            if ((options.AllowedApis & this.SupportedApi) == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(options), $"This device handler doesn't support any of the APIs allowed by the IQuerierOptions (allowed: {options.AllowedApis}, supported {this.SupportedApi}).");
            }

            LazyLoadingDeviceSystemData llsd = lowerLayer.SystemData as LazyLoadingDeviceSystemData;

            if (llsd != null)
            {
                if (oidLookup.TryGetValue(RetrievableValuesEnum.RxSignalStrengthCh0AppendMacAndInterfaceId, out DeviceSpecificOid oid0) && !oid0.Oid.IsNull)
                {
                    // for ALIX/H4L devices we currently only support RSSI querying
                    llsd.SupportedFeatures = DeviceSupportedFeatures.Rssi;
                }
            }
        }
        /// <summary>
        /// Queries the given OIDs and returns the value as string or null if the OID is not available.
        /// </summary>
        /// <param name="lowerLayer">The lower layer engine to extend.</param>
        /// <param name="oids">The OIDs list to query.</param>
        /// <param name="what">Descriptive text what is being queried. Used for debug/error output</param>
        /// <returns>The OID's value as int or or <see cref="int.MinValue" /> if the OID is not available.</returns>
        public static Dictionary <Oid, int> QueryAsInt(this ISnmpLowerLayer lowerLayer, IEnumerable <Oid> oids, string what)
        {
            if (oids == null)
            {
                throw new ArgumentNullException(nameof(oids), "The array of oids to query is null");
            }

            VbCollection queryResult = lowerLayer.Query(oids);

            return(queryResult.ToDictionary(qr => qr.Oid, qr =>
            {
                int retVal = int.MinValue;
                if (!(qr.Value?.TryToInt(out retVal) ?? false))
                {
                    log.Warn($"Querying '{what}' from '{lowerLayer.Address}' as Dictionary<Oid, int>: Conversion to int returned null for response '{qr}'");
                }

                return retVal;
            }));
        }
Exemple #22
0
        /// <summary>
        /// Detects an AirFiber device which does not really provide any manufacturer ID or similar
        /// </summary>
        /// <param name="snmpLowerLayer">The lower communication layer to user.</param>
        /// <returns><c>true</c> if an AirFiber device has been detected and the class fields have been set accordingly.</returns>
        private bool DetectAirFiber(ISnmpLowerLayer snmpLowerLayer)
        {
            var mibInfo41112 = snmpLowerLayer.DoWalk(AirFiberDetectionWalkRootOid);

            if (mibInfo41112.Count == 0)
            {
                // it's also not an AirFiber device
                log.Info($"Reading of OS version of device '{snmpLowerLayer.Address}' via AirFiber OID {AirFiberDetectionWalkRootOid} didn't reveal anything: Assuming the device is not an Ubiquiti AirFiber device");
                return(false);
            }

            // never seen AirFiber returning more than one
            var firstValue = mibInfo41112.First();

            this.osDetectedVersion = firstValue.Value.ToString();
            this.detectionId       = firstValue.Oid.Last();
            this.detectedModel     = AirFiberFakeModelString;

            return(true);
        }
Exemple #23
0
        /// <inheritdoc />
        public override bool IsApplicableSnmp(ISnmpLowerLayer snmpLowerLayer, IQuerierOptions options)
        {
            var description = snmpLowerLayer?.SystemData?.Description;

            if (string.IsNullOrWhiteSpace(description))
            {
                var info = $"Description in system data of device '{snmpLowerLayer.Address}' is null, empty or white-space-only: Assuming the device is not a MikroTik device";
                this.CollectException("AlixSnmp: No device description", new HamnetSnmpException(info));
                log.Warn(info);
                return(false);
            }

            if (!AlixDetectionStrings.Any(ds => description.Contains(ds, StringComparison.InvariantCultureIgnoreCase)))
            {
                var info = $"Description in system data of device '{snmpLowerLayer.Address}' doesn't contain any of the strings string '{string.Join(", ", AlixDetectionStrings)}': Assuming the device is not an ALIX device";
                this.CollectException("AlixSnmp: No ALIX-like string in device description", new HamnetSnmpException(info));
                log.Info(info);
                return(false);
            }

            log.Info($"Device '{snmpLowerLayer.Address}' seems to be an ALIX device");

            return(true);
        }
Exemple #24
0
        /// <inheritdoc />
        public override IDeviceHandler CreateHandler(ISnmpLowerLayer lowerLayer, IQuerierOptions options)
        {
            string osVersionString = "0.0.0";

            // Example: "..."
            Match match = OsVersionExtractionRegex.Match(osVersionString);

            SemanticVersion osVersion = osVersionString.ToSemanticVersion(); // match.Success ? match.Groups[1].Value.ToSemanticVersion() : null;

            var model = lowerLayer.SystemData.Description;                   //lowerLayer.SystemData.Description.Replace(RouterOsDetectionString, string.Empty).Trim();

            log.Info($"Detected device '{lowerLayer.Address}' as ALIX '{model}' v '{osVersion}'");

            DeviceVersion            deviceVersion;
            IDeviceSpecificOidLookup oidTable = this.ObtainOidTable(model.Trim(), osVersion, out deviceVersion, lowerLayer.Address);

            if (string.IsNullOrWhiteSpace(deviceVersion.HandlerClassName))
            {
                try
                {
                    return(new AlixDeviceHandler(lowerLayer, oidTable, osVersion, model, options));
                }
                catch (Exception ex)
                {
                    this.CollectException("AlixSnmp: OID table lookup", ex);

                    // we want to catch and nest the exception here as the APIs involved are not able to append the infomration for which
                    // device (i.e. IP address) the exception is for
                    throw new HamnetSnmpException($"Failed to create ALIX handler for device '{lowerLayer.Address}': {ex.Message}", ex, lowerLayer?.Address?.ToString());
                }
            }
            else
            {
                return(this.GetHandlerViaReflection(deviceVersion.HandlerClassName, lowerLayer, oidTable, osVersion, model, options));
            }
        }
        /// <inheritdoc />
        public override bool IsApplicableSnmp(ISnmpLowerLayer snmpLowerLayer, IQuerierOptions options)
        {
            var description = snmpLowerLayer?.SystemData?.Description;

            if (string.IsNullOrWhiteSpace(description))
            {
                var info = $"Description in system data of device '{snmpLowerLayer.Address}' is null, empty or white-space-only: Assuming the device is not a MikroTik device";
                log.Warn(info);
                this.CollectException("MtikSnmp: No device description", new HamnetSnmpException(info));
                return(false);
            }

            if (!description.Contains(RouterOsDetectionString))
            {
                var info = $"Description in system data of device '{snmpLowerLayer.Address}' doesn't contain string '{RouterOsDetectionString}': Assuming the device is not a MikroTik device";
                log.Info(info);
                this.CollectException("MtikSnmp: No Router-OS-like string in device description", new HamnetSnmpException(info));
                return(false);
            }

            log.Info($"Device '{snmpLowerLayer.Address}' seems to be a MikroTik device");

            return(true);
        }
 /// <inheritdoc />
 protected override IWirelessPeerInfos RetrieveWirelessPeerInfos(ISnmpLowerLayer lowerLayer, IDeviceSpecificOidLookup oidLookup)
 {
     return(new LazyLoadingAlixWirelessPeerInfos(this.LowerLayer, this.OidLookup));
 }
 /// <inheritdoc />
 protected override IInterfaceDetails RetrieveDeviceInterfaceDetails(ISnmpLowerLayer lowerLayer, IDeviceSpecificOidLookup oidLookup)
 {
     return(new LazyLoadingAlixInterfaceDetails(this.LowerLayer, this.OidLookup));
 }
Exemple #28
0
 /// <summary>
 /// Allows deriving class to retrieve and return their implementation of <see cref="IWirelessPeerInfos" />.
 /// </summary>
 /// <param name="lowerLayer">The lower layer for talking to this device.</param>
 /// <param name="oidLookup">The OID lookup table for the device.</param>
 /// <returns>The retrieved interface details.</returns>
 protected abstract IWirelessPeerInfos RetrieveWirelessPeerInfos(ISnmpLowerLayer lowerLayer, IDeviceSpecificOidLookup oidLookup);
Exemple #29
0
 /// <summary>
 /// Constructs for the given lower layer.
 /// </summary>
 /// <param name="lowerLayer">The lower layer for talking to this device.</param>
 /// <param name="oidLookup">The OID lookup table for the device.</param>
 /// <param name="osVersion">The SW version of the device.</param>
 /// <param name="model">The device's model name. Shall be the same name as used for the device name during OID database lookups.</param>
 /// <param name="options">The options to use.</param>
 public GenericDeviceHandler(ISnmpLowerLayer lowerLayer, IDeviceSpecificOidLookup oidLookup, SemanticVersion osVersion, string model, IQuerierOptions options)
     : base(lowerLayer, oidLookup, osVersion, model, options)
 {
 }
Exemple #30
0
 /// <summary>
 /// Allows deriving class to retrieve and return their implementation of <see cref="IInterfaceDetails" />.
 /// </summary>
 /// <param name="lowerLayer">The lower layer for talking to this device.</param>
 /// <param name="oidLookup">The OID lookup table for the device.</param>
 /// <returns>The retrieved interface details.</returns>
 protected abstract IInterfaceDetails RetrieveDeviceInterfaceDetails(ISnmpLowerLayer lowerLayer, IDeviceSpecificOidLookup oidLookup);