/*++ Copyright (c) 1992-1996 Microsoft Corporation Module Name: sess_lm.c Abstract: This file contains MIB_sess_lmget, which actually call lan manager for the session table, copies it into structures, and sorts it to return ready to use by the higher level functions. Environment: User Mode - Win32 Revision History: 10-May-1996 DonRyan Removed banner from Technology Dynamics, Inc. --*/ //--------------------------- WINDOWS DEPENDENCIES -------------------------- //--------------------------- STANDARD DEPENDENCIES -- #include ---- #ifdef WIN32 #include #include #endif #include #include #include #include #include //--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------ #include "mib.h" #include "mibfuncs.h" #include "sess_tbl.h" #include "lmcache.h" //--------------------------- SELF-DEPENDENCY -- ONE #include"module.h" ----- //--------------------------- PUBLIC VARIABLES --(same as in module.h file)-- //--------------------------- PRIVATE CONSTANTS ----------------------------- #define SafeBufferFree(x) if(NULL != x) NetApiBufferFree( x ) #define SafeFree(x) if(NULL != x) SnmpUtilMemFree( x ) //--------------------------- PRIVATE STRUCTS ------------------------------- //--------------------------- PRIVATE VARIABLES ----------------------------- //--------------------------- PRIVATE PROTOTYPES ---------------------------- int __cdecl sess_entry_cmp( IN const SESS_ENTRY *A, IN const SESS_ENTRY *B ) ; BOOL build_sess_entry_oids( ); void FreeSessTable(); //--------------------------- PRIVATE PROCEDURES ---------------------------- //--------------------------- PUBLIC PROCEDURES ----------------------------- // // MIB_sess_lmset // Perform the necessary actions to SET a field in the Session Table. // // Notes: // // Return Codes: // // Error Codes: // None. // UINT MIB_sess_lmset( IN AsnObjectIdentifier *Index, IN UINT Field, IN AsnAny *Value ) { NET_API_STATUS lmCode; int Found; UINT Entry; AsnInteger ErrStat = SNMP_ERRORSTATUS_NOERROR; char Client[MAX_PATH]; char User[MAX_PATH]; #ifdef UNICODE LPWSTR UniClient; LPWSTR UniUser; #endif // Must make sure the table is in memory if ( SNMPAPI_ERROR == MIB_sess_lmget() ) { ErrStat = SNMP_ERRORSTATUS_GENERR; goto Exit; } // Find a match in the table if ( MIB_TBL_POS_FOUND != MIB_sess_match(Index, &Entry, FALSE) ) { ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME; goto Exit; } // Check for action on Table if ( Value->asnValue.number == SESS_STATE_DELETED ) { strcpy( Client, "\\\\" ); if (MIB_SessionTable.Table[Entry].svSesClientName.length <= MAX_PATH-3) { memcpy( &Client[2], MIB_SessionTable.Table[Entry].svSesClientName.stream, MIB_SessionTable.Table[Entry].svSesClientName.length ); Client[MIB_SessionTable.Table[Entry].svSesClientName.length+2] = '\0'; } else { ErrStat = SNMP_ERRORSTATUS_GENERR; goto Exit; } if (MIB_SessionTable.Table[Entry].svSesUserName.length <= MAX_PATH-1) { memcpy( User, MIB_SessionTable.Table[Entry].svSesUserName.stream, MIB_SessionTable.Table[Entry].svSesUserName.length ); User[MIB_SessionTable.Table[Entry].svSesUserName.length] = '\0'; } else { ErrStat = SNMP_ERRORSTATUS_GENERR; goto Exit; } #ifdef UNICODE if (SnmpUtilUTF8ToUnicode(&UniClient, Client, TRUE )) { ErrStat = SNMP_ERRORSTATUS_RESOURCEUNAVAILABLE; goto Exit; } if (SnmpUtilUTF8ToUnicode(&UniUser, User, TRUE )) { SnmpUtilMemFree(UniClient); ErrStat = SNMP_ERRORSTATUS_RESOURCEUNAVAILABLE; goto Exit; } lmCode = NetSessionDel( NULL, UniClient, UniUser ); SnmpUtilMemFree(UniClient); SnmpUtilMemFree(UniUser); #else // Call the LM API to delete it lmCode = NetSessionDel( NULL, Client, User ); #endif // Check for successful operation switch( lmCode ) { case NERR_Success: // Make cache be reloaded next time cache_table[C_SESS_TABLE].bufptr = NULL; break; case NERR_ClientNameNotFound: case NERR_UserNotFound: ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME; break; default: ErrStat = SNMP_ERRORSTATUS_GENERR; } } Exit: return ErrStat; } // MIB_sess_lmset // // MIB_sess_lmget // Retrieve session table information from Lan Manager. // If not cached, sort it and then // cache it. // // Notes: // // Return Codes: // SNMPAPI_NOERROR // SNMPAPI_ERROR // // Error Codes: // None. // SNMPAPI MIB_sess_lmget( ) { DWORD entriesread; DWORD totalentries; LPBYTE bufptr=NULL; unsigned lmCode; unsigned i; SESSION_INFO_2 *DataTable; SESS_ENTRY *MIB_SessionTableElement ; int First_of_this_block; time_t curr_time ; SNMPAPI nResult = SNMPAPI_NOERROR; LPSTR tempbuff = NULL; DWORD resumehandle=0; DWORD dwAllocatedEntries=0; time(&curr_time); // get the time //return nResult; // OPENISSUE remember the problem with the error // every time a free is done from this call to Enum? // // // If cached, return piece of info. // // if((NULL != cache_table[C_SESS_TABLE].bufptr) && (curr_time < (cache_table[C_SESS_TABLE].acquisition_time + cache_expire[C_SESS_TABLE] ) ) ) { // it has NOT expired! goto Exit ; // the global table is valid } // // // Do network call to gather information and put it in a nice array // // // free the old table LOOK OUT!! FreeSessTable(); First_of_this_block = 0; do { // as long as there is more data to process lmCode = NetSessionEnum( NULL, // local server NULL, // get server stats NULL, 2, // level &bufptr, // data structure to return MAX_PREFERRED_LENGTH, &entriesread, &totalentries, NULL //&resumehandle // resume handle ); if(NULL == bufptr) return nResult ; DataTable = (SESSION_INFO_2 *) bufptr ; if((NERR_Success == lmCode) || (ERROR_MORE_DATA == lmCode)) { // valid so process it, otherwise error if(0 == MIB_SessionTable.Len) { // 1st time, alloc the whole table // alloc the table space MIB_SessionTable.Table = SnmpUtilMemAlloc(totalentries * sizeof(SESS_ENTRY) ); if (NULL == MIB_SessionTable.Table) { // free all of the lan man data SafeBufferFree( bufptr ); nResult = SNMPAPI_ERROR; goto Exit; } dwAllocatedEntries = totalentries; } MIB_SessionTableElement = MIB_SessionTable.Table + First_of_this_block ; for(i=0; (isvSesClientName.dynamic = TRUE; #ifdef UNICODE if (SnmpUtilUnicodeToUTF8( &MIB_SessionTableElement->svSesClientName.stream, DataTable->sesi2_cname, TRUE)) { MIB_SessionTableElement->svSesClientName.stream = NULL; MIB_SessionTableElement->svSesClientName.length = 0; MIB_SessionTableElement->svSesClientName.dynamic = FALSE; } else { MIB_SessionTableElement->svSesClientName.length = strlen (MIB_SessionTableElement->svSesClientName.stream); } #else MIB_SessionTableElement->svSesClientName.stream = SnmpUtilMemAlloc ( strlen( DataTable->sesi2_cname )+1 ) ; MIB_SessionTableElement->svSesClientName.length = strlen( DataTable->sesi2_cname ) ; memcpy( MIB_SessionTableElement->svSesClientName.stream, DataTable->sesi2_cname, strlen( DataTable->sesi2_cname ) ) ; #endif // user name MIB_SessionTableElement->svSesUserName.dynamic = TRUE; #ifdef UNICODE if (SnmpUtilUnicodeToUTF8( &MIB_SessionTableElement->svSesUserName.stream, DataTable->sesi2_username, TRUE)) { MIB_SessionTableElement->svSesUserName.length = 0; MIB_SessionTableElement->svSesUserName.stream = NULL; MIB_SessionTableElement->svSesUserName.dynamic = FALSE; } else { MIB_SessionTableElement->svSesUserName.length = strlen(MIB_SessionTableElement->svSesUserName.stream); } #else MIB_SessionTableElement->svSesUserName.stream = SnmpUtilMemAlloc ( strlen( DataTable->sesi2_username ) + 1 ) ; MIB_SessionTableElement->svSesUserName.length = strlen( DataTable->sesi2_username ) ; memcpy( MIB_SessionTableElement->svSesUserName.stream, DataTable->sesi2_username, strlen( DataTable->sesi2_username ) ) ; #endif // number of connections MIB_SessionTableElement->svSesNumConns = // DataTable->sesi2_num_conns ; LM_NOT_THERE 0 ; // so get ready in case somebody implements // number of opens MIB_SessionTableElement->svSesNumOpens = DataTable->sesi2_num_opens ; // session time MIB_SessionTableElement->svSesTime = DataTable->sesi2_time ; // session idle time MIB_SessionTableElement->svSesIdleTime = DataTable->sesi2_idle_time ; // client type parsing // first convert from unicode if needed #ifdef UNICODE if (SnmpUtilUnicodeToUTF8( &tempbuff, DataTable->sesi2_cltype_name, TRUE)) { MIB_SessionTableElement->svSesClientType = 0 ; } else { #else tempbuff = SnmpUtilMemAlloc( strlen(DataTable->sesi2_cltype_name) + 1 ); memcpy( tempbuff, DataTable->sesi2_cltype_name, strlen( DataTable->sesi2_cltype_name ) ) ; #endif // let's assume 0 is undefined but better than garbage ... MIB_SessionTableElement->svSesClientType = 0 ; if(0==strcmp( "DOWN LEVEL", tempbuff)) MIB_SessionTableElement->svSesClientType = 1 ; else if(0==strcmp("DOS LM", tempbuff)) MIB_SessionTableElement->svSesClientType = 2 ; else if(0==strcmp("DOS LM 2.0", tempbuff)) MIB_SessionTableElement->svSesClientType = 3 ; else if(0==strcmp("OS/2 LM 1.0", tempbuff)) MIB_SessionTableElement->svSesClientType = 4 ; else if(0==strcmp("OS/2 LM 2.0", tempbuff)) MIB_SessionTableElement->svSesClientType = 5 ; else if(0==strcmp("DOS LM 2.1", tempbuff)) MIB_SessionTableElement->svSesClientType = 6 ; else if(0==strcmp("OS/2 LM 2.1", tempbuff)) MIB_SessionTableElement->svSesClientType = 7 ; else if(0==strcmp("AFP 1.1", tempbuff)) MIB_SessionTableElement->svSesClientType = 8 ; else if(0==strcmp("AFP 2.0", tempbuff)) MIB_SessionTableElement->svSesClientType = 9 ; else if(0==strcmp("NT", tempbuff)) MIB_SessionTableElement->svSesClientType = 10 ; SnmpUtilMemFree(tempbuff); tempbuff = NULL; #ifdef UNICODE } #endif // state is always active, set uses to indicate delete request MIB_SessionTableElement->svSesState = 1; //always active DataTable ++ ; // advance pointer to next sess entry in buffer MIB_SessionTableElement ++ ; // and table entry } // for each entry in the data table // free all of the lan man data SafeBufferFree( bufptr ) ; // indicate where to start adding on next pass, if any First_of_this_block += i ; } // if data is valid to process else { // Signal error nResult = SNMPAPI_ERROR; goto Exit; } } while (ERROR_MORE_DATA == lmCode) ; // iterate over the table populating the Oid field if (! build_sess_entry_oids()) { SNMPDBG(( SNMP_LOG_TRACE, "SNMP: LMMIB2: build_sess_entry_oids failed\n.")); FreeSessTable(); cache_table[C_SESS_TABLE].bufptr = NULL; nResult = SNMPAPI_ERROR; goto Exit; } // Sort the table information using MSC QuickSort routine qsort( (void *)&MIB_SessionTable.Table[0], (size_t)MIB_SessionTable.Len, (size_t)sizeof(SESS_ENTRY), sess_entry_cmp ); // // // Cache table // // if(0 != MIB_SessionTable.Len) { cache_table[C_SESS_TABLE].acquisition_time = curr_time ; cache_table[C_SESS_TABLE].bufptr = bufptr ; } // // // Return piece of information requested // // Exit: return nResult; } // MIB_sess_get // // MIB_sess_cmp // Routine for sorting the session table. // // Notes: // // Return Codes: // SNMPAPI_NOERROR // SNMPAPI_ERROR // // Error Codes: // None. // int __cdecl sess_entry_cmp( IN const SESS_ENTRY *A, IN const SESS_ENTRY *B ) { // Compare the OID's return SnmpUtilOidCmp( (AsnObjectIdentifier *)&A->Oid, (AsnObjectIdentifier *)&B->Oid ); } // MIB_sess_cmp // // None. // BOOL build_sess_entry_oids( ) { AsnOctetString OSA ; AsnObjectIdentifier UserNameOid ; SESS_ENTRY *SessEntry ; unsigned i; // start pointer at 1st guy in the table SessEntry = MIB_SessionTable.Table ; // now iterate over the table, creating an oid for each entry for( i=0; isvSesClientName, &SessEntry->Oid )) { return FALSE; } // copy the user name into a temporary oid buffer if (! MakeOidFromStr( &SessEntry->svSesUserName, &UserNameOid )) { return FALSE; } // append the two entries forming the index if (! SnmpUtilOidAppend( &SessEntry->Oid, &UserNameOid )) { SnmpUtilOidFree( &UserNameOid ); return FALSE; } // free the temporary buffer SnmpUtilOidFree( &UserNameOid ); SessEntry++; // point to the next guy in the table } // for return TRUE; } // build_sess_entry_oids void FreeSessTable() { UINT i; SESS_ENTRY *MIB_SessionTableElement ; MIB_SessionTableElement = MIB_SessionTable.Table ; if (MIB_SessionTableElement) { // iterate over the whole table for(i=0; iOid)); SnmpUtilMemFree(MIB_SessionTableElement->svSesClientName.stream); SnmpUtilMemFree(MIB_SessionTableElement->svSesUserName.stream); MIB_SessionTableElement ++ ; // increment table entry } SnmpUtilMemFree(MIB_SessionTable.Table) ; // free the base Table } MIB_SessionTable.Table = NULL ; // just for safety MIB_SessionTable.Len = 0 ; // just for safety } //-------------------------------- END --------------------------------------