/*++
*******************************************************************************
* Copyright (c) 1990-2000 Digi International Inc., All Rights Reserved		  *
* 																			  *
* This software contains proprietary and confidential information of Digi	  *
* International Inc.  By accepting transfer of this copy, Recipient agrees	  *
* to retain this software in confidence, to prevent disclosure to others,	  *
* and to make no use of this software other than that for which it was		  *
* delivered.  This is an unpublished copyrighted work of Digi International	  *
* Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly	  *
* prohibited.																  *
* 																			  *
* Restricted Rights Legend													  *
*																			  *
* Use, duplication, or disclosure by the Government is subject to			  *
* restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in		  *
* Technical Data and Computer Software clause at DFARS 252.227-7031 or		  *
* subparagraphs (c)(1) and (2) of the Commercial Computer Software -		  *
* Restricted Rights at 48 CFR 52.227-19, as applicable.						  *
*																			  *
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343		  *
*																			  *
*******************************************************************************

Module Name:

   x25dll.c

Abstract:

    X.25 MIB SNMP Extension Agent for Windows NT.

    These files (x25dll.c, x25mib.c, and x25mib.h) provide an 
    Extension Agent DLL which works in conjunction with the SNMP 
    Extendible Agent for Windows NT.

    This SNMP Extension Agent was derived from the sample on the Microsoft
    Developer's Toolkit. See the "Microsoft Windows/NT SNMP Programmer's Reference".

Author:

   Carl Caldwell

--*/
// General notes:
//
//   Microsoft's Extendible Agent for Windows NT is implemented by dynamically
// linking to Extension Agent DLLs that implement portions of the MIB.  These
// Extension Agents are configured in the Windows NT Registration Database.
// When the Extendible Agent Service is started, it queries the registry to
// determine which Extension Agent DLLs have been installed and need to be
// loaded and initialized.  The Extendible Agent invokes various DLL entry
// points (examples follow in this file) to request MIB queries and obtain
// Extension Agent generated traps.

// Contains definitions for the table structure describing the MIB.  This
// is used in conjunction with testmib.c where the MIB requests are resolved.
#include "x25mib.h"


// Extension Agent DLLs need access to elapsed time agent has been active.
// This is implemented by initializing the Extension Agent with a time zero
// reference, and allowing the agent to compute elapsed time by subtracting
// the time zero reference from the current system time.  This example
// Extension Agent implements this reference with dwTimeZero.

DWORD dwTimeZero = 0;


// Extension Agent DLLs that generate traps must create a Win32 Event object
// to communicate occurence of traps to the Extendible Agent.  The event
// handle is given to the Extendible Agent when the Extension Agent is 
// initialized, it should be NULL if traps will not be generated.  This
// example Extension Agent simulates the occurance of traps with hSimulateTrap.

HANDLE hX25Trap = NULL;

// The data collection thread will be started after MIB initialization. This thread
// will be started by a routine in rs232mib.c that returns the thread handle. If the
// thread terminates the DLL entry point is called at the thread_detach point. This 
// id will be used to determine that the thread died. At this point we will need to 
// notify everyone that the thread is dead so all future requests can fail, and write
// an event out to the event log.

DWORD  lpSxbDataCollectorThreadId;
DWORD  lpSxbTraceCollectorThreadId;

// Handle used to control the data acquisition thread

HANDLE hSxbCollectionThread;
HANDLE hSxbTraceCollectionThread;

// The following structure is used to build a port information list from the 
// registry. It contains the informtaion describing each port as required to 
// initialize the MIB structures.

PSXB_PORT_INFO   pSxbPortInfo;

// The following structure is used to access the SXB driver. It contains all
// the information used in collecting information. It is created as a linked
// list so it will be available for expansion and compression. 

PX25_SXB_IOCTL_INFO   pX25SxbInfo;

// This structure contains the global var holding the ioctl structures for the
// X.25 SNMP tracing facility. It is a global var that is a linked list structure 
// containing an IOCTL, as well as the necessary configuration information
PX25_SXB_EVENT_IOCTL_INFO	pSxbAdapterIoctl;

// This structure contains the global var holding the structures for the event
// tracing routines. It is a global var that is a structure containing 
// pointer to the port structures and the event ioctl strucures
PSXB_COLLECTOR_PARM_STRUCT	pSxbParmInfo;

// Termination event handle
HANDLE	terminateEvent;

// This structure ties a call parm mib entry to a circuit mib entry. This is used
// to track Call Parameter and Call Cleared events
PMIB_CircuitCallBindTable_t pCircuitCallBindTable;

// The X.25 Extension agent DLL needs to process restart and reset trap events
// when thay occur. These events are kept on a linked list. Whenever a trap 
// event occurs, the hX25Trap event will be signalled. The Extendible agent will
// then poll the driver at the SnmpExtensionTrap entry point until all events are 
// exhausted from the queue.
extern PX25SNMP_TrapListEntry pX25TrapListEntry = NULL;

// Buffer for formatted Debug messages
extern char	DbgBuf[80];

// The following counter tracks threads that attach to the DLL. When the last 
// one releases, we shut down the driver.
//int		attachedProcessCount = 0;

#ifdef	SNMP_DLL_DEBUG
char	DebugStr[80];
#endif

// This is a standard Win32 DLL entry point.  See the Win32 SDK for more
// information on its arguments and their meanings.  This example DLL does 
// not perform any special actions using this mechanism.

BOOL WINAPI DllMain(
    HANDLE hDll,
    DWORD  dwReason,
    LPVOID lpReserved)
{

		switch(dwReason)
		{
			case DLL_PROCESS_ATTACH:
#ifdef SNMP_DLL_DEBUG
				OutputDebugString("X25: DLL_PROCESS_ATTACH Entry Point\n");
#endif
				break;

			case DLL_PROCESS_DETACH:
#ifdef SNMP_DLL_DEBUG
				OutputDebugString("X.25: DLL_PROCESS_DETACH Entry Point\n");
#endif
				x25_Terminate_MIB_Data_Collection(pX25SxbInfo, pSxbPortInfo);
				break;
        
			case DLL_THREAD_ATTACH:
#ifdef SNMP_DLL_DEBUG
				OutputDebugString("X.25: DLL_THREAD_ATTACH Entry Point \n");
#endif
				break;
        
			case DLL_THREAD_DETACH:
#ifdef SNMP_DLL_DEBUG
				OutputDebugString("X.25: DLL_THREAD_DETACH Entry Point\n");
#endif
				break;
        
			default:
#ifdef SNMP_DLL_DEBUG
				OutputDebugString("X.25: UNKNOWN Dll Entry Point\n");
#endif
				break;

		} // end switch()

    return TRUE;
} // end DllEntryPoint()


// Extension Agent DLLs provide the following entry point to coordinate the
// initializations of the Extension Agent and the Extendible Agent.  The
// Extendible Agent provides the Extension Agent with a time zero reference;
// and the Extension Agent provides the Extendible Agent with an Event handle 
// for communicating occurence of traps, and an object identifier representing
// the root of the MIB subtree that the Extension Agent supports.

BOOL WINAPI SnmpExtensionInit(
    IN  DWORD               dwTimeZeroReference,
    OUT HANDLE              *hPollForTrapEvent,
    OUT AsnObjectIdentifier *supportedView)
{

    UINT    initStatus;         //Keep track of results from called routines
	
    // Create an event that waits on termination notification
	terminateEvent = CreateEvent( NULL,
								  TRUE,
								  FALSE,
								  NULL );

	// Record the time reference provided by the Extendible Agent.
    dwTimeZero = dwTimeZeroReference;

    // Create an Event that will be used to communicate the occurence of traps
    // to the Extendible Agent.  The Extension Agent will assert this Event
    // when a trap has occured.  This is explained further later in this file.

    if ((*hPollForTrapEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL)
    {
        // Indicate error?, be sure that NULL is returned to Extendible Agent.
    }

    // Indicate the MIB view supported by this Extension Agent, an object
    // identifier representing the sub root of the MIB that is supported.
    *supportedView = MIB_OidPrefix; // NOTE!  structure copy

    // Record the trap Event.  This example Extension Agent simulates traps by 
    // generating a trap after every given number of processed requests.
    hX25Trap = *hPollForTrapEvent;

	// Allocate the Circuit-Call binding table
	if ((pCircuitCallBindTable = SNMP_malloc(sizeof(MIB_CircuitCallBindTable_t))) == NULL)
	{
		DebugBreak();
		return FALSE;
	}
	
	//Initialize the SXB Port Information structures  
    if ((pSxbPortInfo = SNMP_malloc(sizeof(struct SXB_PORT_INFO))) == NULL)
	{
		DebugBreak();
		return FALSE;
	}

	if ( x25_Init_Sxb_Port_Info(pSxbPortInfo) != 0 )
	{
		//DebugBreak();
		return FALSE;
	}

	//Initialize the SXB driver data collection structures  
    if ((pX25SxbInfo = SNMP_malloc(sizeof(struct X25_SXB_IOCTL_INFO))) == NULL)
	{
		DebugBreak();
		return FALSE;
	}

	if ( x25_Init_MIB_Data_Structures(pX25SxbInfo, pSxbPortInfo) != 0 )
	{
		DebugBreak();
		return FALSE;
	}

    // Initialize the tables in the MIB from the registry values created when the
    // WAN Links product was installed
    if ((initStatus = InitMibTableEntries(pX25SxbInfo, pSxbPortInfo)) != SNMP_ERRORSTATUS_NOERROR)
	{
		return FALSE;
	}

	//Start the SXB data collector thread
	if ((hSxbCollectionThread =  CreateThread(
										NULL,
										0,
										(LPTHREAD_START_ROUTINE)x25_Update_MIB_Data,
										pX25SxbInfo,
										0,
										&lpSxbDataCollectorThreadId
									)) == NULL)
	{
		// Indicate that Extension Agent initialization was sucessful
		DebugBreak();
		return FALSE;
	}

	//Initialize the SXB Port Information structures  
    if ((pSxbAdapterIoctl = SNMP_malloc(sizeof(struct X25_SXB_EVENT_IOCTL_INFO))) == NULL)
	{
		DebugBreak();
		return FALSE;
	}

	//Initialize the SXB Trace Information structure
    if ((pSxbParmInfo = SNMP_malloc(sizeof(struct SXB_COLLECTOR_PARM_STRUCT))) == NULL)
	{
		DebugBreak();
		return FALSE;
	}
	// Initialize the structure passed to the sxb event handling thread
	pSxbParmInfo->pSxbPortInfoParm       = pSxbPortInfo;
	pSxbParmInfo->pSxbEventIoctlInfoParm = pSxbAdapterIoctl;
									
	//Start the SXB trace data collector thread
	if ((hSxbTraceCollectionThread =  CreateThread(
										NULL,
										0,
										(LPTHREAD_START_ROUTINE)x25_Sxb_Trace_Data_Collection,
										pSxbParmInfo,
										0,
										&lpSxbTraceCollectorThreadId
									)) == NULL)
	{
		// Indicate that Extension Agent initialization was sucessful
		DebugBreak();
		return FALSE;
	}
	return TRUE;
} // end SnmpExtensionInit()


// Extension Agent DLLs provide the following entry point to resolve queries
// for MIB variables in their supported MIB view (supplied at initialization
// time).  The requestType is Get/GetNext/Set.
BOOL WINAPI SnmpExtensionQuery(
    IN BYTE                   requestType,
    IN OUT RFC1157VarBindList *variableBindings,
    OUT AsnInteger            *errorStatus,
    OUT AsnInteger            *errorIndex)
{
    static unsigned long requestCount = 0;  // Supports the trap simulation.
    UINT    I;


    // Iterate through the variable bindings list to resolve individual
    // variable bindings.

    for ( I=0;I < variableBindings->len;I++ )
    {
        *errorStatus = ResolveVarBind( &variableBindings->list[I],
                                       requestType );

        // Test and handle case where Get Next past end of MIB view supported
        // by this Extension Agent occurs.  Special processing is required to 
        // communicate this situation to the Extendible Agent so it can take 
        // appropriate action, possibly querying other Extension Agents.
        if ( *errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME &&
             requestType == MIB_ACTION_GETNEXT )
        {
           *errorStatus = SNMP_ERRORSTATUS_NOERROR;


           // Modify variable binding of such variables so the OID points
           // just outside the MIB view supported by this Extension Agent.
           // The Extendible Agent tests for this, and takes appropriate
           // action.
           SNMP_oidfree( &variableBindings->list[I].name );
           SNMP_oidcpy( &variableBindings->list[I].name, &MIB_OidPrefix );
           variableBindings->list[I].name.ids[MIB_PREFIX_LEN-1] ++;
        }

        // If an error was indicated, communicate error status and error
        // index to the Extendible Agent.  The Extendible Agent will ensure
        // that the origional variable bindings are returned in the response
        // packet.
        if ( *errorStatus != SNMP_ERRORSTATUS_NOERROR )
        {
    	   *errorIndex = I+1;
	       goto Exit;
	    }
    }

Exit:
    // Indicate that Extension Agent processing was sucessfull.
    return SNMPAPI_NOERROR;

} // end SnmpExtensionQuery()
