+---------------------------------------------------------------+ | (tm) | | Product : Visual xAgentBuilder 9 for C++ | +---------------------------------------------------------------+ Visual xAgentBuilder© 9 for C++ is a C++ Code Generator for standalone Multiprotocol (SNMPv3/HTTP/CLI) Windows Agent or SNMP extensions DLL for NuDesign SNMP Multiprototcol (SNMPv3/HTTP) Agent Service or MS Windows SNMP Agent Service. When coupled with appropriate NuDesign's SDK, the Visual xAgentBuilder© 9 for C++ generates standalone Multiprotocol (SNMPv3/HTTP/CLI) Agent code for Linux and a number of embedded RTOS/OS platforms. Supported host environments are Windows XP/Vista/Win7. +-----------------+ | Version History | +-----------------+ ver 9.8 - Sep 1, 2017 - Added support for VS2017 ver 9.7 - Feb 20, 2017 - NDSWCryp - added support for SHA 224/256/384/512, AES 192/256, 3DES 256 - NDSnmp - added option to add VBL to authFailure trap - NDAgentX - fixed "context" handling - fixed upper bound in subtree registration/unregistration ver 9.6 - Feb 02, 2016 - Code Generator - fixed SnmpExtensionTrap - updated extension dll reg file template - option _SUPPRESS_DATETIME is set to 1 by deafult - NDSys - add name to TSemaphore. - add rfind() to BString - NDSocket - add second BSockStream::Read() method - change BSockStream::WaitReadable() into two method, original interface still exists, calls newer one. - add new NDERR_SOCKET_CONN_CLOSED macro. - NDMibH - change QueryGetNext() to prevent crash if subtree handler isn't found in multiple varbind request. - fixed getnext caching - correct error index returned when an authorization error is determined during GetNext processing. - add method BMibSubtreeHandler::SetContext - NDSnmp - update for configurable support to allow V1 to Inform up conversion. - add new method FindUsmUser(), updated one of the AddUsmUser() methods. - allow USM users to use a lesser security level than that implied by it's definition. E.g. allow a USMUser with auth & priv protocol definitions to communicate with authNoPriv. - correct issue where engine boots didn't latch at 0x7fffffff - NDVacm - add method Remove(secModel, secName) - NDAgentX - change ReceiveAndProcessData() to prevent recurring errors when master aborts abnormally. - fixed sending traps from mib handler callbacks - NDSXDll - register nonoverlapping regions with agent service ver 9.5 - Re-release Nov 12, 2015 - Added support for VS2013 and VS2015 ver 9.5 - Re-release Jun 28, 2013 - SDK fixes: - handling of row creation (set request with multiple rowStatus varbinds) - extension dll registers only non-overlapping subtrees ver 9.5 - Re-release Feb 26, 2013 - Added support for VS2012 - Tutorial sample projects now use SxS SDK. - Updated help files. ver 9.5 - Oct 9, 2012 - Fixed code generator wizard script (keyboard events handling) - Fixed name of log file ver 9.2 - Nov 15, 2011 - IPv6 support - AgentX (rfc 2741) remote subagents - Code generator wizard requires VS 2008 and up - minor changes for rfc compliance (error codes) ver 8.7.1 - Mar 30, 2011 - Code Generator - added option _SUPPRESS_DATETIME; when set to 1 date/time stamp will not be inserted in generated file header - Added wizard for VS 2010 ver 8.7 - Feb 25, 2009 - NDSnmp - Improved SNMP tracing - Added ToString method to BSnmpPdu & BSnmpMessage - A message published while restarting worker thread contains extended info: decoded packet, remote address, protocol - Fixed setting of row status in commit/undo phase in usmUserTable for key-change columns - Fixed SendNotifications (exclude 'non active' rows in notify table) - Fixed UpdateMaxMsgSize in CBSecurity - NDMibH - Added option to remove serialized access to single subtree handler. By default stack guards from simultaneous execution of callbacks in the same subtree handler by two (or more) threads. User that disables serialization (by calling NDSerialializeSHAccess(false);) allows two different callbacks from the same subtree handler to be executed simultaneously. Also, there is a possibility of callback reentrancy, i.e callback can be partially executed by one thread, reentered by another thread, and then resumed from the original thread. Serialization of access to shared data (mutual exclusion,...), either global or member of subtree handler, is responsibility of the user. - Added IsAccessAllowedEx to IAccessControl interface. Default implementation simply calls IsAccessAllowed. BMibHandler calls IsAccessAllowedEx during processing of getNext request. User can override this method to optimize getNext processing. - Fixed BFilterTable::Filter (boundary condition, search for previous row) - Fixed handling of RowStatus in BMibTableImplEx (failure in commit phase while the new row is being created would prevent creation of the row with the same index in the future) - NDVacm - Added tracing - NDSys - Fixed singleWriter/multiReader synch - NDSubAg - Fixed subtree handler registration/unregistration ver 8.6.2 - Nov 17, 2008 - NDSnmp - Fixed handling of row creation in snmpCommunityTable - Fixed BCBSecurity::ProcessIncomingMsg - skip non-active rows in snmpCommunityTable - Fixed error status mapping for proxy forwarding when upstream version is greater than downstream version - Fixed counters: unknownPDUHandlers, unknownContexts, and unavailableContexts. Corresponding report is being sent on each counter increment. - Fixed contextEngineId field in outgoing messages containing report PDU (rfc3412, 3.d.2) - NDMibH - Added IsContextAvailable to IAccessControl interface. Default implementation always returns true. User should override this method to check context availability. - Fixed handling of the IsAccessAllowed return statuses (BMibHandler::Query...) - NDVacm - Call IsContextAvailable in BViewBasedAccessControl::IsAccessAllowed. - NDSProxy - Fixed BSnmpProxyForwarder::ProcessPdu - skip non-active rows in snmpProxyTable - Fixed handling of snmpProxyTable - prevent changing of snmpProxyType while the row is active, allow changes of snmpProxyStorageType while the row is active ver 8.6.1- Oct 15, 2008 - NDSnmp - Truncate too long privacy keys specified in configuration to proper length ver 8.6 - Oct 02, 2008 - NDSnmp - Fixed handling of row creation in snmpTargetAddrExtTable - Fixed handling of USM Key Change - Fixed handling of USM row status Row created remotely in usmUserTable for a user who employs authenticationcan not be made 'active' until corresponding usmUserCloneFrom and usmUserAuthKeyChange have been set. Row created remotely in usmUserTable for a user who also employs privacy, cannot be made active until the usmUserPrivKeyChange has been set - Added snmpTargeAddrExt table look-up during processing of v1/v2c request in v3 agent - NDVacm - Fixed SplitIndex in vacmAccessTable - Fixed row creation in vacmSecurityToGroup table when createAndGo is used for row status - NDMibH - Fixed handling of row create request - agent was crashing when request contained no index - Fixed handling of mib2.sysServices - NDSsi - Added thread to manage SSI request ids - Added more response format options - Code Generator - Added wizard for VS 2008 - Generate code from TRAP-TYPE (SMIv1); By default, generated classes are excluded from build. User must explicitly define XV1TRAPS preprocessor macro to build generated code. ver 8.5.1 - May 23, 2008 - HTML page generator - uses new MIBTABLE SSI tag for MIB table presentation, GETTABLE is obsoleted NDxABhtml.cfg file is used to configure output of HTML page generator - generated pages could contain context sensitive help per object (based on DESCRIPTION clause), parameter "description=yes" in NDxABhtml.cfg - valid range for MIB objects could be generated along with object name (based on SYNTAX clause), parameter "constraints=yes" in NDxABhtml.cfg - index column could be omitted for MIB table presentation, parameter "indexcolumn=no" in NDxABhtml.cfg - NDSnmp - "permitted managers" can be dynamically added/removed - NDSsi - Added new SSI tag: MIBTABLE. GETTABLE is obsoleted - NDMibH - Fixed handling of Set request for RowStatus/EntryStatus column If user code returns error code other then noError or noSuchName from OnGet... handler method, set processing is aborted - NDSXDll - Fixed handling of Set request - cleanup phase was skipped when test phase failed for row creation ver 8.4 - Removed dependency on libeay32.dll for AES Cipher Algorithm, All cryptographic algorithms are now based on Windows Crypto API. - Code Generator - Fixed IsIndexValid for tables with multiple integer indices ver 8.3 - Sep 20, 2007 - Code Generator - Fixed request handler method prototypes for MIB objects with syntax SnmpSecurityLevel, TruthValue and StorageType. These sytaxes are enumerations declared in MibImpl.h. Generated prototypes have Integer as an argument instead of enumeration. - Fixed IsIndexValid and SplitIndex for tables with multiple octet-string indices - NDSocket - Fixed BSockDgrmArray - added check for socket validity before calling FD_ISSET. Note that this was not an issue in winsock implementation, only in some embedded OS-es. - NDSnmp - Increment snmpInASNParseErrs if message contains valid BER encoding but does not follow teh correct SNMP message format (for example version is encoded as octet string instead of integer) - Fixed incrementing of snmpUnknownPDUHandlers and snmpSilentDrops - Fixed snmpv2/v3 response pdu containing error, comand responder was removing vblist form the response pdu which is correct only for 'tooBig' error - NDMibH - Fixed handling of multiphase set request. Number of UNDOs didn't match number of COMMITs in case RowStatus varbind is not the 1st vb in varbind list. - Relaxed restriction on error code to be returned in each phase of SET request. Previously if commit failed, engine overrode error code with commitFailed, and if undo failed, engine set the error code to undoFailed. The code generated by xAgentBuilder returns the proper code in each phase, but user is allowed to change it. ver 8.2 - Apr 24, 2007 - NDMibH - Overloaded Filter method in BFilterTable class. New method provides number of matches found to the caller - NDSnmp - Fixed notification filtering - previous version filtered only snmpTrapOID varbind ver 8.1 - Feb 07, 2007 - NDMibH - Added GetLocalUdpPort and GetRemoteUdpPort to BTransaction class - Changed processing of GetNext/GetBulk - MIB handler aborts further processing on any error except noSuchName - fixed BMibInfo::IsLeaf(const BObjectIdentifier& oid) - NDSnmp - Fixed error-status values generated for SNMPv2 access to MIB data, values readOnly, noSuchName and badValue are ot allowed in SNMPv2/v3 responses - Changed processing of GetNext/GetBulk (see NDMibH above) - agent aborts further processing on any error except noSuchName and error response is sent to the manager - Fixed Getbulk processing - negative values in no-repeaters and max-repetitions are reset to zero (RFC 3416) -NDSys - Changed implementation of NDAlloc/NDRealloc/NDFree - user can supply his own memory management by creating NDHeap.dll and implementing NDHeapAlloc, NDHeapReAlloc, and NDHeapFree functions. Simply put NDHeap.dll in the same directory as agent executable, and memory alloc/free will be redirected to implementation in NDHeap.dll. ver 8.0 - Aug 25, 2006 - NDSWCryp/NDSCryp - added AES Cipher Algorithm (requires libeay32.dll - crypto lib from openssl) - NDSnmp - added AES to USM (Rfc 3826) - NDSubAg - added tracing to BSAMaster & BSASubAgent - NDSXDll - fixed "UNDO" problem (undo was not being called after commit failed) this problem affected only Extension DLLs, not standalone agent - Code Generator - added code to turn console agent into Master agent - added code to turn on tracing in console agent (EXE) and remote subagent (REM) projects ver 7.0 - Jan 17, 2006 - NDSubAg (***NEW***) - adds remote subagent capability to the framework - NDSWCryp (***NEW***) - BWinCrypto class - implementation of ISnmpCrypto interface using Microsoft CryptoAPI >>>>> IMPORTANT <<<<< NDSCryp (BSslCrypto class) is not shipped in Win32 distribution of xAgentBuilder any more. If you upgrade xAgentBuilder to 7.0, and don't want to recompile your agent, simply rename NDSWCryp.dll to NDSCryp.dll, or use NDSCryp from the previous release. - NDSnmp - Fixed agent response to GET request (RFC3416 (SNMPv2); pp.10-11) - Fixed method RemoveFromTheListOfPermittedManagers in BSnmpEngine class ver 6.4.0.1 - APR, 2005 - Code generator - Fixed index creation and manipulation methods for tables with indices with octetString or OID syntax with fixed length (for example if index has syntax MacAddress) - Fixed InitFromNV for augmented tables (missing temporary integer variable declaration) ver 6.4 - Feb. 11, 2005 - NDMibH – Fixed BCounter64::ToString, and BObjectSyntax ValToStr for counter 64 types – Fixed BCounter64::ToString, and BObjectSyntax ValToStr for counter 64 types – Altered BOctetString::Assign() to allow assignment from an empty BOctetString. – Altered BMibImpl::Get() and Set() to make it more fault tolerant. – Integrate with GoAhead 2.18 code base. - enable user management. - CGI interface. – Conditionally include ReadFile() into INonVolatile class. - NDSnmp - Added SetThreadsPriority to TThreadDispatcher - Fixed SNMPv3 notification filtering - Fixed receiving SNMPv3 authNoPriv & authPriv Traps - NDSAgent - Added configuration param "ThreadsPriority" - NDSys - Fixed BString::Assign - Added m_name to TThread (conditionally, does not affect win32 release) - NDSsi - Fixed parsing (lines longer than 1024 chars) - Code generator - changed generated "persist" file name to .txt (was Persist.txt) to acomodate 8.3 restriction in some file systems (project name must be shorter than or equal to 8 characters though) ver 6.3 - Oct 18, 2004 - NDNVol – Fixed read/write tabular values with one column only - NDSsi - GETTABLE – “noenums” shows only numeric value for columns that have enumeration values - NDMibH - Fixed sysORTable implementation - Fixed SNMP SET operation on objects of type DisplayString (RFC 2579) - Fixec nosuchInstance/noSuchObject handling (RFC 3416) - NDSnmp/NDSProxy - Fixed SNMPv3 Proxy Forwarder for SNMPv1/v2c (RFC 3413) - NDxABhtml - Changed array index operator from () to [] in generated javascript (causes problem with some web browser) - NDSAgent - Fixed BSNMPAgent::SendTrap for agent started in v1/v2c mode ver 6.2 - Sep 2004 - synchronized code for various OS-es, Win32 not affected ver 6.1 - July 02, 2004 - NDMibH - Improved handling of the dynamic row creation request (createRequest(v1) or createAndGo/createAndWait(v2c, v3) can be anywhere in the vb-list, in the old version it had to be the 1st vb in the vblist) - Code generator - Fixed code generated for EntryStatus defined locally (EntryStatus was originally defined in RMON-MIB (rfc 1757) and code generated for MIBs that import EntryStatus from RMON-MIB was correct) - Fixed constraints table, entry was not being added for INTEGER Textual Conventions with further restriction (e.g. original TC has range (1..32000), and TC derived from it (100..500)) Ver 6.0 - Feb 18, 2004 - NDSproxy (*** NEW ***) - SNMPv3 Proxy Forwarder library - xAgentBuilder adds (conditionally compiled) code for proxy to standalone (console) agent project. Macro ND_SNMPv3_PROXY controls whether agent will include proxy or not. NOTE: This is not complete implementation of proxy forwarder, it forwards only v3 messages (to v1/v2c/v3 targets). Support for forwarding of incoming v1/v2c messages will be added in the upcoming release. - NDMibH - Added global functions: NDGetLocalIpAddress, and NDGetRemoteIpAddress. The first argument for these functions is 'transactionId', which is the one passed in each OnGet.../OnSet... method in MIB instrumentation classes. Developer can use these functions to retrieve local/remote ip address of the request that is being processed. In order to get meaningful values for Local and Remote Ip Address, BSNMPAgentEx should be used instead of BSNMPAgent in the agent code (see NDSAgent below). NOTE: These function will provide meaningful results only for SNMP (if BSNMPAgentEx is used) and CLI (if optional ip address is specified in command, see below). - Added optional parameter -aIpAddress to all CLI commands that retrieve/modify MIB objects. For example: # get 1.3.6.1.2.1.1.4.0 -a192.168.0.2 Ip address specified in the command will be returned from call to NDGetLocalIpAddress while this request is being processed. If address is omitted, NDGetLocalIpAddress will return '0.0.0.0' - Added global function NDGetParameters that replaces ITransactions::GetParameters. Implementation of the ITransactions is still present, but is deprecated and may be removed in the future release. - NDSnmp - Fixed authNoPriv/authPriv SNMPv3 trap receiving - NDSocket - Added global function NDGetHostName - NDSAgent - Added new class BSNMPAgentEx that binds to individual addresses when initialized. BSNMPAgent binds to INADDR_ANY. The purpose of BSNMPAgentEx is to provide information for NDGetLocalIpAddress, and NDGetRemoteIpAddress functions (see NDMibH above). - NDSys - Fixed constructors for TMUtex, TSemaphore & TEvent. Creating object of any of these classes with 1st argument bInitialize set to false, was causing assertion. - NDWebs - Removed implementation of websGetCgiCommName function. Cgi was not used, and this function was not directly portable to other OS-s. - Code generator & Visual Studio Wizards (VS C++ 6.0 and VS .NET 2002/2003) - Added support for SNMPv3 Proxy Forwarder Ver 5.6 - Dec 10, 2003 - NDMibH - BTestAndIncr - IsSuccessfullyTested returns true if spinlock implemented using this class is not included in the request. This makes usage of spin-lock optional (or advisory, i.e. it is good practise to use it, but if it is not used it won;t prevent execution of the request) - NDSnmp - Fixed indexing in BTargetAddrTable, BTargetParamsTable and BNotifyFilterTable (IMPLIED) - Added implementation of snmpTargetAddrExtTable. This table augments snmpTargetAddrTable (two objects from snmpTargetAddrExtTable are added to BTargetAddrTable, class CTargetAddrExtTable handles SNMP) Updated BCBSecurity (it checks snmpTargetAddrExtTable's TMAsk to determine whether request would be rejected or processed) - NDSsi - fixed parsing of index of type IP address in set request Ver 5.5 - May 08, 2003 - NDMibH - sysDescr and sysObjectID are now configurable through NV - Added BPtrArray class to collections (handles array of void*) - Added two methods INonVolatile interface and created INVCallback interface to provide means for dynamic NV updates - Implemented INVCallback interface in CSystem class - NDNVol - Implemented new methods declared in INonVolatile interface - NDSnmp - Fixed createAndWait handling - Fixed BTargetAddrTable and CTargetAddrTable classes (changes to TagList column done through SNMP request were not saved in the cross-ref table used for sending notifications) - Implemented INVCallback interface in all classes that read from/ save to NV - NDVacm - Implemented INVCallback interface in all classes that read from/ save to NV - Code generator - fixed usage of external NV in generated code (constructor of class) Ver 5.4 - Apr 15, 2003 - Code generator - fixed usage of external NV in generated code (constructor of class) - NDSnmp - changed processing of "unknownEngineId" report (allow match regardless of the requestId value in the pdu) - added automatic send of request after notInTimeWindow report - fixed processing of invalid v3 request (pdu is Confirmed class, but Reportable Flag is zero) - fixed sending of generic v1trap when engine is initialized in v1 mode Ver 5.3 - Apr 07, 2003 - NDSnmp - fixed bug in processing incoming secure SNMPv3 message - added "errors" topic to help Ver 5.2 - Mar 27, 2003 - Code generator - fixed DebugDLL.reg and ReleaseDLL.reg - (HTML plug-in) changed extension of created files to 'htm' to accomodate Agent Service requirements - NDSAgent - saves config to NV on exit (SaveToNV made public) - redesigned Init so it can be called multiple times until suceeds Ver 5.1 - Mar 12, 2003 - Code generator (HTML plug-in) - - create XMI (Xagentbuilder Mib Info) file. Required by agent service to expose extension DLL objects through HTML - NDMibH - updated sysORTable handling in BMib2System class Ver 5.0 - Feb 2003 - Multiprotocol xAgentBuilder Ver 4.5 - Oct 23, 2002 - Added support for VisualStudio .NET Ver 4.4 - June 04, 2002 - Code generator - Fix - exception was thrown in case when subtree contains augmenting table and xAgentBuilder settings are: ImplementTables=no(0), ImplementPersistence=no(0) Ver 4.3 - May 10, 2002 - NDSnmp3 - class BSnmpNotifOriginator - added varbind list parameter to the SendGenericTrapV1 method - removed deprecated methods - Code generator - Changed step 1 so user can select standalone, extension DLL or BOTH as the project target If BOTH types of project are selected, standalone will have the name chosen for the project, and extension DLL project name will have "DLL" appended to it. Only one set of source files will be created an dincluded in both projects (the only difference between standalone and extension DLL agent is in one file: standalone has 'main.cpp' while ext dll has 'dllmain.cpp'. - Fix - exception was thrown in case when augmenting table only was selected (base table not selected) - Fix - exception was thrown in case when table index(es) referred to non implemeted objects Ver 4.2 - Feb 7, 2002 - NDSnmp3 - Fix - Decoding of improperly encoded requests - Change - added varbind list parameter to the generic v1Trap version of INotifOriginator::Notify. - NDSock - Class BUdpTransport was limited to 32 transport endpoints (sockets). New constructor is provided so user can increase/decrease this number. Ver 4.1 - Dec 19, 2001 - NDSnmp3 - Fix - assert condition in BAddress - NDCryp - Fix - DES encyption failed when key was longer than 16 octets - Code generator - Fix - code in CreateDemoRow for tables with scalar object as index caused unresolved reference compiler error Ver 4.0 - Nov 22, 2001 ***** IMPORTANT ****** * - DLLs in this version are not binary compatible with DLLs from the version 3.3. * Code generated by the xAgentBuilder C++ code generator is still the same. * Users have to rebuild old projects after installing this version. * The only change required is in the link settings (Two DLLs and corresponding export libs * now have different names) * NDCrypto(D)(E).dll is now NDCryp(D)(E).dll * NDSnmp3X(D)(E).dll is now NDS3Ex(D)(E).dll * * - Format for the NV configuration file for the agent has changed. * Please consult help file for the description of the new format. * Agent configuration application is now part of the package. ********************** - NDSnmp3 - Fixed crashing of the agent when set request is attempted on the read-only object. - StdTypes.h file contains typedefs for the standard types used in the DLLs. - INotifOriginator interface has changed - BSnmpNotifOriginator class implements both old and new INotifOriginator interface. Using methods from the old INotifOriginator interface is deprecated though. - Added BV3CommunityTable class (implements snmpCommunityTable from SNMP-COMMUNITY-MIB) - Changed structure of the security subsystem. New structure simplifies user extensions. Addedd class BSecurity that contains objects of BUserBasedSecurity and BCBSecurity class. BCBSecurity implements handling of the SNMPv1/v2c messages when agent is running in SNMPv3 mode. - ITransport interface has changed. New method 'ResolveAddress' is added. - ISnmpCrypto interface has changed. New methods 'PasswordToKey' and 'LocalizeKey' are added. - NDCryp (formerly NDCrypto) - name of the DLL has changed - implements new methods from ISnmpCrypto interface - NDSock - implements new methods from ITransport interface - NDS3Ex (formerly NDSnmp3X) - name of the DLL has changed - Code generator - Fix - objects with enum syntax used as indexes in the table were not casted properly causing compiler error - Fix - code generated for tables when the option ImplementTables is set to "no(0)" produced not compilable code. - Added - typedefs are generated for all Textual convention definitions (not just for enums) and corresponding name is now used for the class member variable Ver 3.3 - Aug 30, 2001 - TMutex and TSempahore classes now create and use unnamed synchronization objects - fixed synchronization of buffer for encoding/decoding scoped pdu (class BSnmpMsgProcessor) - fixed encryption of v3 response pdu - added inline method to retrieve BSnmpEngine object used in BSnmpAgent and BSnmpManager - fixed Remove method in BVacmContextTable - fixed BIpAddress::Set(unsigned char a[]) - fixed binding to local loopback address (127.0.0.1) on machines without network card Ver 3.2 - July 13, 2001 - fixed AUGMENTS related problems - Augmented variables were not saved to NV nor restored from NV. - Augmented table data could not be accessed via get-next. Ver 3.1 - June 29, 2001 - fixed a problem restoring data to a MIB table. ver 3.0 - June 20, 2001 - Added v3 capabilities. ver 1.5 - Mar 09, 2001 - Yet another fix of BITS syntax ver 1.4 - Jan 31, 2001 - Fixed generation of code for tables with scalar indices - Fixed handling of BITS syntax ver 1.3 - Dec 07, 2000 - Fixed generation of code for tables with duplicate indices (for example protocolDirLocalIndex is used twice in alMatrixDSTable in RMON-2) - Updated application icons ver 1.2 - Aug 30, 2000 - Addedd support for accessing SNMP agent configuration (including transaction parameters) from extension DLL ver 1.1 - Aug 10, 2000 - bug fix (NDSnmp2.dll): Set request on read-only object caused exception during cleanup phase. ver 1.0 - Aug 01, 2000 - initial release For Technical Support: Tel: (416) 737-0328 Fax: (416) 445-9101 Email: contact@ndt-inc.com