• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 using System;
2 using System.Collections.Generic;
3 using System.Text.RegularExpressions;
4 using Lextm.SharpSnmpLib.Mib.Elements;
5 using Lextm.SharpSnmpLib.Mib.Elements.Entities;
6 using Lextm.SharpSnmpLib.Mib.Elements.Types;
7 
8 namespace Lextm.SharpSnmpLib.Mib
9 {
10 	 public static class MibTypesResolver
11 	 {
12 		  private static readonly Regex              _namedOidPathRegex = new Regex(@"^(?<Name>[^\(]+)\((?<Value>\d+)\)$");
13 		  private static readonly List<IMibResolver> _resolver      = new List<IMibResolver>();
14 		  private static readonly List<IModule>      _cachedModules = new List<IModule>();
15 
RegisterResolver(IMibResolver resolver)16 		  public static void RegisterResolver(IMibResolver resolver)
17 		  {
18 				if (resolver != null)
19 				{
20 					 _resolver.Add(resolver);
21 				}
22 		  }
23 
ResolveModule(string moduleName)24 		  public static IModule ResolveModule(string moduleName)
25 		  {
26 				// check if module is already cached
27 				foreach (MibModule cachedModule in _cachedModules)
28 				{
29 					 if (cachedModule.Name == moduleName)
30 					 {
31 						  return cachedModule;
32 					 }
33 				}
34 
35 				foreach (IMibResolver resolver in _resolver)
36 				{
37 					 IModule resolvedModule = resolver.Resolve(moduleName);
38 					 if (resolvedModule != null)
39 					 {
40 						  ResolveTypes(resolvedModule);
41 						  _cachedModules.Add(resolvedModule);
42 						  return resolvedModule;
43 					 }
44 				}
45 
46 				return null;
47 		  }
48 
ResolveTypes(IModule module)49 		  public static void ResolveTypes(IModule module)
50 		  {
51 				foreach (IEntity entity in module.Entities)
52 				{
53 					 ITypeReferrer typeReferringEntity = entity as ITypeReferrer;
54 
55 					 if (typeReferringEntity != null)
56 					 {
57 						  CheckTypeReferrer(module, typeReferringEntity);
58 					 }
59 				}
60 
61 				if (!_cachedModules.Contains(module))
62 				{
63 					 _cachedModules.Add(module);
64 				}
65 		  }
66 
CheckTypeReferrer(IModule module, ITypeReferrer typeReferringEntity)67 		  private static void CheckTypeReferrer(IModule module, ITypeReferrer typeReferringEntity)
68 		  {
69 				TypeAssignment unknownType = typeReferringEntity.ReferredType as TypeAssignment;
70 				if (unknownType != null)
71 				{
72 					 typeReferringEntity.ReferredType = ResolveType(module, unknownType);
73 
74 					 if (typeReferringEntity.ReferredType is TypeAssignment)
75 					 {
76 						  Console.WriteLine(String.Format("Could not resolve type '{0}' declared in module '{1}'", (typeReferringEntity.ReferredType as TypeAssignment).Type, typeReferringEntity.ReferredType.Module.Name));
77 					 }
78 				}
79 
80 				ITypeReferrer nextTypeReferringEntity = typeReferringEntity.ReferredType as ITypeReferrer;
81 				if (nextTypeReferringEntity != null)
82 				{
83 					 CheckTypeReferrer(module, nextTypeReferringEntity);
84 				}
85 		  }
86 
ResolveType(IModule module, TypeAssignment type)87 		  public static ITypeAssignment ResolveType(IModule module, TypeAssignment type)
88 		  {
89 				ITypeAssignment result = ResolveDeclaration(module, type.Type) as ITypeAssignment;
90 
91 				return (result != null) ? result : type;
92 		  }
93 
ResolveDeclaration(IModule module, string name)94 		  public static IDeclaration ResolveDeclaration(IModule module, string name)
95 		  {
96 				if ((module == null) || String.IsNullOrEmpty(name))
97 				{
98 					 return null;
99 				}
100 
101 				// check module internal types
102 				foreach (IDeclaration decl in module.Declarations)
103 				{
104 				if (decl.Name == name)
105 					 {
106 					return decl;
107 					 }
108 				}
109 
110 				// check if type is imported
111 				if (module.Imports != null)
112 				{
113 					 ImportsFrom imports = module.Imports.GetImportFromType(name);
114 					 if (imports != null)
115 					 {
116 						  IModule importedModule = ResolveModule(imports.Module);
117 						  if (importedModule != null)
118 						  {
119 								return ResolveDeclaration(importedModule, name);
120 						  }
121 					 }
122 				}
123 
124 				return null;
125 		  }
126 
ResolveOid(IEntity entity)127 		  public static ObjectIdentifier ResolveOid(IEntity entity)
128 		  {
129 				ObjectIdentifier result = new ObjectIdentifier();
130 
131 				if (entity != null)
132 				{
133 					 ResolveOid(entity, result);
134 				}
135 
136 				return result;
137 		  }
138 
ResolveOid(IEntity entity, ObjectIdentifier result)139 		  private static void ResolveOid(IEntity entity, ObjectIdentifier result)
140 		  {
141 				result.Prepend(entity.Name, entity.Value);
142 
143 				// check parent
144 				if (!String.IsNullOrEmpty(entity.Parent))
145 				{
146 					 string[] pathParts = entity.Parent.Split('.');
147 					 uint value;
148 
149 					 // all parts except the first should have their value directly or indirectly with them
150 					 if (pathParts.Length > 1)
151 					 {
152 						  for (int i=pathParts.Length-1; i>=1; i--)
153 						  {
154 								if (uint.TryParse(pathParts[i], out value))
155 								{
156 									 result.Prepend("", value);
157 								}
158 								else
159 								{
160 									 Match m = _namedOidPathRegex.Match(pathParts[i]);
161 									 if (m.Success)
162 									 {
163 										  result.Prepend(m.Groups["Name"].Value, uint.Parse(m.Groups["Value"].Value));
164 									 }
165 									 else
166 									 {
167 										  throw new MibException("Invalid OID path detected for entity '" + entity.Name + "' in module '" + entity.Module + "'!");
168 									 }
169 								}
170 						  }
171 					 }
172 
173 					 // parse root part: either another entity or a standard root object
174 					 if (IsOidRoot(pathParts[0], out value))
175 					 {
176 						  result.Prepend(pathParts[0], value);
177 					 }
178 					 else
179 					 {
180 						  // try to find entity inside this module
181 						  if (entity.Module != null)
182 						  {
183 								entity = ResolveDeclaration(entity.Module, pathParts[0]) as IEntity;
184 
185 								if (entity != null)
186 								{
187 									 ResolveOid(entity, result);
188 								}
189 								else
190 								{
191 									 result.Prepend("", uint.MaxValue);
192 								}
193 						  }
194 						  else
195 						  {
196 								result.Prepend("", uint.MaxValue);
197 						  }
198 					 }
199 				}
200 		  }
201 
IsOidRoot(string name, out uint value)202 		  public static bool IsOidRoot(string name, out uint value)
203 		  {
204 				value = uint.MaxValue;
205 
206 				switch (name)
207 				{
208 					 case "ccitt": value = 0; return true;
209 					 case "iso": value = 1; return true;
210 					 case "joint-iso-ccitt": value = 2; return true;
211 				}
212 
213 				return false;
214 		  }
215 	 }
216 }
217