Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

610 lines
18 KiB

  1. /*++
  2. Copyright (c) 1992-1996 Microsoft Corporation
  3. Module Name:
  4. sess_lm.c
  5. Abstract:
  6. This file contains MIB_sess_lmget, which actually call lan manager
  7. for the session table, copies it into structures, and sorts it to
  8. return ready to use by the higher level functions.
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. 10-May-1996 DonRyan
  13. Removed banner from Technology Dynamics, Inc.
  14. --*/
  15. //--------------------------- WINDOWS DEPENDENCIES --------------------------
  16. //--------------------------- STANDARD DEPENDENCIES -- #include<xxxxx.h> ----
  17. #ifdef WIN32
  18. #include <windows.h>
  19. #include <lm.h>
  20. #endif
  21. #include <tchar.h>
  22. #include <string.h>
  23. #include <search.h>
  24. #include <stdlib.h>
  25. #include <time.h>
  26. //--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------
  27. #include "mib.h"
  28. #include "mibfuncs.h"
  29. #include "sess_tbl.h"
  30. #include "lmcache.h"
  31. //--------------------------- SELF-DEPENDENCY -- ONE #include"module.h" -----
  32. //--------------------------- PUBLIC VARIABLES --(same as in module.h file)--
  33. //--------------------------- PRIVATE CONSTANTS -----------------------------
  34. #define SafeBufferFree(x) if(NULL != x) NetApiBufferFree( x )
  35. #define SafeFree(x) if(NULL != x) SnmpUtilMemFree( x )
  36. //--------------------------- PRIVATE STRUCTS -------------------------------
  37. //--------------------------- PRIVATE VARIABLES -----------------------------
  38. //--------------------------- PRIVATE PROTOTYPES ----------------------------
  39. int __cdecl sess_entry_cmp(
  40. IN const SESS_ENTRY *A,
  41. IN const SESS_ENTRY *B
  42. ) ;
  43. BOOL build_sess_entry_oids( );
  44. void FreeSessTable();
  45. //--------------------------- PRIVATE PROCEDURES ----------------------------
  46. //--------------------------- PUBLIC PROCEDURES -----------------------------
  47. //
  48. // MIB_sess_lmset
  49. // Perform the necessary actions to SET a field in the Session Table.
  50. //
  51. // Notes:
  52. //
  53. // Return Codes:
  54. //
  55. // Error Codes:
  56. // None.
  57. //
  58. UINT MIB_sess_lmset(
  59. IN AsnObjectIdentifier *Index,
  60. IN UINT Field,
  61. IN AsnAny *Value
  62. )
  63. {
  64. NET_API_STATUS lmCode;
  65. int Found;
  66. UINT Entry;
  67. AsnInteger ErrStat = SNMP_ERRORSTATUS_NOERROR;
  68. char Client[MAX_PATH];
  69. char User[MAX_PATH];
  70. #ifdef UNICODE
  71. LPWSTR UniClient;
  72. LPWSTR UniUser;
  73. #endif
  74. // Must make sure the table is in memory
  75. if ( SNMPAPI_ERROR == MIB_sess_lmget() )
  76. {
  77. ErrStat = SNMP_ERRORSTATUS_GENERR;
  78. goto Exit;
  79. }
  80. // Find a match in the table
  81. if ( MIB_TBL_POS_FOUND != MIB_sess_match(Index, &Entry, FALSE) )
  82. {
  83. ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME;
  84. goto Exit;
  85. }
  86. // Check for action on Table
  87. if ( Value->asnValue.number == SESS_STATE_DELETED )
  88. {
  89. strcpy( Client, "\\\\" );
  90. if (MIB_SessionTable.Table[Entry].svSesClientName.length <= MAX_PATH-3)
  91. {
  92. memcpy( &Client[2], MIB_SessionTable.Table[Entry].svSesClientName.stream,
  93. MIB_SessionTable.Table[Entry].svSesClientName.length );
  94. Client[MIB_SessionTable.Table[Entry].svSesClientName.length+2] = '\0';
  95. }
  96. else
  97. {
  98. ErrStat = SNMP_ERRORSTATUS_GENERR;
  99. goto Exit;
  100. }
  101. if (MIB_SessionTable.Table[Entry].svSesUserName.length <= MAX_PATH-1)
  102. {
  103. memcpy( User, MIB_SessionTable.Table[Entry].svSesUserName.stream,
  104. MIB_SessionTable.Table[Entry].svSesUserName.length );
  105. User[MIB_SessionTable.Table[Entry].svSesUserName.length] = '\0';
  106. }
  107. else
  108. {
  109. ErrStat = SNMP_ERRORSTATUS_GENERR;
  110. goto Exit;
  111. }
  112. #ifdef UNICODE
  113. if (SnmpUtilUTF8ToUnicode(&UniClient,
  114. Client,
  115. TRUE ))
  116. {
  117. ErrStat = SNMP_ERRORSTATUS_RESOURCEUNAVAILABLE;
  118. goto Exit;
  119. }
  120. if (SnmpUtilUTF8ToUnicode(&UniUser,
  121. User,
  122. TRUE ))
  123. {
  124. SnmpUtilMemFree(UniClient);
  125. ErrStat = SNMP_ERRORSTATUS_RESOURCEUNAVAILABLE;
  126. goto Exit;
  127. }
  128. lmCode = NetSessionDel( NULL, UniClient, UniUser );
  129. SnmpUtilMemFree(UniClient);
  130. SnmpUtilMemFree(UniUser);
  131. #else
  132. // Call the LM API to delete it
  133. lmCode = NetSessionDel( NULL, Client, User );
  134. #endif
  135. // Check for successful operation
  136. switch( lmCode )
  137. {
  138. case NERR_Success:
  139. // Make cache be reloaded next time
  140. cache_table[C_SESS_TABLE].bufptr = NULL;
  141. break;
  142. case NERR_ClientNameNotFound:
  143. case NERR_UserNotFound:
  144. ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME;
  145. break;
  146. default:
  147. ErrStat = SNMP_ERRORSTATUS_GENERR;
  148. }
  149. }
  150. Exit:
  151. return ErrStat;
  152. } // MIB_sess_lmset
  153. //
  154. // MIB_sess_lmget
  155. // Retrieve session table information from Lan Manager.
  156. // If not cached, sort it and then
  157. // cache it.
  158. //
  159. // Notes:
  160. //
  161. // Return Codes:
  162. // SNMPAPI_NOERROR
  163. // SNMPAPI_ERROR
  164. //
  165. // Error Codes:
  166. // None.
  167. //
  168. SNMPAPI MIB_sess_lmget(
  169. )
  170. {
  171. DWORD entriesread;
  172. DWORD totalentries;
  173. LPBYTE bufptr=NULL;
  174. unsigned lmCode;
  175. unsigned i;
  176. SESSION_INFO_2 *DataTable;
  177. SESS_ENTRY *MIB_SessionTableElement ;
  178. int First_of_this_block;
  179. time_t curr_time ;
  180. SNMPAPI nResult = SNMPAPI_NOERROR;
  181. LPSTR tempbuff = NULL;
  182. DWORD resumehandle=0;
  183. DWORD dwAllocatedEntries=0;
  184. time(&curr_time); // get the time
  185. //return nResult; // OPENISSUE remember the problem with the error
  186. // every time a free is done from this call to Enum?
  187. //
  188. //
  189. // If cached, return piece of info.
  190. //
  191. //
  192. if((NULL != cache_table[C_SESS_TABLE].bufptr) &&
  193. (curr_time <
  194. (cache_table[C_SESS_TABLE].acquisition_time
  195. + cache_expire[C_SESS_TABLE] ) ) )
  196. { // it has NOT expired!
  197. goto Exit ; // the global table is valid
  198. }
  199. //
  200. //
  201. // Do network call to gather information and put it in a nice array
  202. //
  203. //
  204. // free the old table LOOK OUT!!
  205. FreeSessTable();
  206. First_of_this_block = 0;
  207. do { // as long as there is more data to process
  208. lmCode =
  209. NetSessionEnum( NULL, // local server
  210. NULL, // get server stats
  211. NULL,
  212. 2, // level
  213. &bufptr, // data structure to return
  214. MAX_PREFERRED_LENGTH,
  215. &entriesread,
  216. &totalentries,
  217. NULL //&resumehandle // resume handle
  218. );
  219. if(NULL == bufptr) return nResult ;
  220. DataTable = (SESSION_INFO_2 *) bufptr ;
  221. if((NERR_Success == lmCode) || (ERROR_MORE_DATA == lmCode))
  222. { // valid so process it, otherwise error
  223. if(0 == MIB_SessionTable.Len) { // 1st time, alloc the whole table
  224. // alloc the table space
  225. MIB_SessionTable.Table = SnmpUtilMemAlloc(totalentries *
  226. sizeof(SESS_ENTRY) );
  227. if (NULL == MIB_SessionTable.Table)
  228. {
  229. // free all of the lan man data
  230. SafeBufferFree( bufptr );
  231. nResult = SNMPAPI_ERROR;
  232. goto Exit;
  233. }
  234. dwAllocatedEntries = totalentries;
  235. }
  236. MIB_SessionTableElement = MIB_SessionTable.Table + First_of_this_block ;
  237. for(i=0; (i<entriesread) && ((i+First_of_this_block) < dwAllocatedEntries); i++) { // once for each entry in the buffer
  238. // increment the entry number
  239. MIB_SessionTable.Len ++;
  240. // Stuff the data into each item in the table
  241. // client name
  242. MIB_SessionTableElement->svSesClientName.dynamic = TRUE;
  243. #ifdef UNICODE
  244. if (SnmpUtilUnicodeToUTF8(
  245. &MIB_SessionTableElement->svSesClientName.stream,
  246. DataTable->sesi2_cname,
  247. TRUE))
  248. {
  249. MIB_SessionTableElement->svSesClientName.stream = NULL;
  250. MIB_SessionTableElement->svSesClientName.length = 0;
  251. MIB_SessionTableElement->svSesClientName.dynamic = FALSE;
  252. }
  253. else
  254. {
  255. MIB_SessionTableElement->svSesClientName.length =
  256. strlen (MIB_SessionTableElement->svSesClientName.stream);
  257. }
  258. #else
  259. MIB_SessionTableElement->svSesClientName.stream = SnmpUtilMemAlloc (
  260. strlen( DataTable->sesi2_cname )+1 ) ;
  261. MIB_SessionTableElement->svSesClientName.length =
  262. strlen( DataTable->sesi2_cname ) ;
  263. memcpy( MIB_SessionTableElement->svSesClientName.stream,
  264. DataTable->sesi2_cname,
  265. strlen( DataTable->sesi2_cname ) ) ;
  266. #endif
  267. // user name
  268. MIB_SessionTableElement->svSesUserName.dynamic = TRUE;
  269. #ifdef UNICODE
  270. if (SnmpUtilUnicodeToUTF8(
  271. &MIB_SessionTableElement->svSesUserName.stream,
  272. DataTable->sesi2_username,
  273. TRUE))
  274. {
  275. MIB_SessionTableElement->svSesUserName.length = 0;
  276. MIB_SessionTableElement->svSesUserName.stream = NULL;
  277. MIB_SessionTableElement->svSesUserName.dynamic = FALSE;
  278. }
  279. else
  280. {
  281. MIB_SessionTableElement->svSesUserName.length =
  282. strlen(MIB_SessionTableElement->svSesUserName.stream);
  283. }
  284. #else
  285. MIB_SessionTableElement->svSesUserName.stream = SnmpUtilMemAlloc (
  286. strlen( DataTable->sesi2_username ) + 1 ) ;
  287. MIB_SessionTableElement->svSesUserName.length =
  288. strlen( DataTable->sesi2_username ) ;
  289. memcpy( MIB_SessionTableElement->svSesUserName.stream,
  290. DataTable->sesi2_username,
  291. strlen( DataTable->sesi2_username ) ) ;
  292. #endif
  293. // number of connections
  294. MIB_SessionTableElement->svSesNumConns =
  295. // DataTable->sesi2_num_conns ; LM_NOT_THERE
  296. 0 ; // so get ready in case somebody implements
  297. // number of opens
  298. MIB_SessionTableElement->svSesNumOpens =
  299. DataTable->sesi2_num_opens ;
  300. // session time
  301. MIB_SessionTableElement->svSesTime =
  302. DataTable->sesi2_time ;
  303. // session idle time
  304. MIB_SessionTableElement->svSesIdleTime =
  305. DataTable->sesi2_idle_time ;
  306. // client type parsing
  307. // first convert from unicode if needed
  308. #ifdef UNICODE
  309. if (SnmpUtilUnicodeToUTF8(
  310. &tempbuff,
  311. DataTable->sesi2_cltype_name,
  312. TRUE))
  313. {
  314. MIB_SessionTableElement->svSesClientType = 0 ;
  315. }
  316. else
  317. {
  318. #else
  319. tempbuff = SnmpUtilMemAlloc( strlen(DataTable->sesi2_cltype_name) + 1 );
  320. memcpy( tempbuff,
  321. DataTable->sesi2_cltype_name,
  322. strlen( DataTable->sesi2_cltype_name ) ) ;
  323. #endif
  324. // let's assume 0 is undefined but better than garbage ...
  325. MIB_SessionTableElement->svSesClientType = 0 ;
  326. if(0==strcmp( "DOWN LEVEL",
  327. tempbuff))
  328. MIB_SessionTableElement->svSesClientType = 1 ;
  329. else if(0==strcmp("DOS LM",
  330. tempbuff))
  331. MIB_SessionTableElement->svSesClientType = 2 ;
  332. else if(0==strcmp("DOS LM 2.0",
  333. tempbuff))
  334. MIB_SessionTableElement->svSesClientType = 3 ;
  335. else if(0==strcmp("OS/2 LM 1.0",
  336. tempbuff))
  337. MIB_SessionTableElement->svSesClientType = 4 ;
  338. else if(0==strcmp("OS/2 LM 2.0",
  339. tempbuff))
  340. MIB_SessionTableElement->svSesClientType = 5 ;
  341. else if(0==strcmp("DOS LM 2.1",
  342. tempbuff))
  343. MIB_SessionTableElement->svSesClientType = 6 ;
  344. else if(0==strcmp("OS/2 LM 2.1",
  345. tempbuff))
  346. MIB_SessionTableElement->svSesClientType = 7 ;
  347. else if(0==strcmp("AFP 1.1",
  348. tempbuff))
  349. MIB_SessionTableElement->svSesClientType = 8 ;
  350. else if(0==strcmp("AFP 2.0",
  351. tempbuff))
  352. MIB_SessionTableElement->svSesClientType = 9 ;
  353. else if(0==strcmp("NT",
  354. tempbuff))
  355. MIB_SessionTableElement->svSesClientType = 10 ;
  356. SnmpUtilMemFree(tempbuff);
  357. tempbuff = NULL;
  358. #ifdef UNICODE
  359. }
  360. #endif
  361. // state is always active, set uses to indicate delete request
  362. MIB_SessionTableElement->svSesState = 1; //always active
  363. DataTable ++ ; // advance pointer to next sess entry in buffer
  364. MIB_SessionTableElement ++ ; // and table entry
  365. } // for each entry in the data table
  366. // free all of the lan man data
  367. SafeBufferFree( bufptr ) ;
  368. // indicate where to start adding on next pass, if any
  369. First_of_this_block += i ;
  370. } // if data is valid to process
  371. else
  372. {
  373. // Signal error
  374. nResult = SNMPAPI_ERROR;
  375. goto Exit;
  376. }
  377. } while (ERROR_MORE_DATA == lmCode) ;
  378. // iterate over the table populating the Oid field
  379. if (! build_sess_entry_oids())
  380. {
  381. SNMPDBG((
  382. SNMP_LOG_TRACE,
  383. "SNMP: LMMIB2: build_sess_entry_oids failed\n."));
  384. FreeSessTable();
  385. cache_table[C_SESS_TABLE].bufptr = NULL;
  386. nResult = SNMPAPI_ERROR;
  387. goto Exit;
  388. }
  389. // Sort the table information using MSC QuickSort routine
  390. qsort( (void *)&MIB_SessionTable.Table[0], (size_t)MIB_SessionTable.Len,
  391. (size_t)sizeof(SESS_ENTRY), sess_entry_cmp );
  392. //
  393. //
  394. // Cache table
  395. //
  396. //
  397. if(0 != MIB_SessionTable.Len) {
  398. cache_table[C_SESS_TABLE].acquisition_time = curr_time ;
  399. cache_table[C_SESS_TABLE].bufptr = bufptr ;
  400. }
  401. //
  402. //
  403. // Return piece of information requested
  404. //
  405. //
  406. Exit:
  407. return nResult;
  408. } // MIB_sess_get
  409. //
  410. // MIB_sess_cmp
  411. // Routine for sorting the session table.
  412. //
  413. // Notes:
  414. //
  415. // Return Codes:
  416. // SNMPAPI_NOERROR
  417. // SNMPAPI_ERROR
  418. //
  419. // Error Codes:
  420. // None.
  421. //
  422. int __cdecl sess_entry_cmp(
  423. IN const SESS_ENTRY *A,
  424. IN const SESS_ENTRY *B
  425. )
  426. {
  427. // Compare the OID's
  428. return SnmpUtilOidCmp( (AsnObjectIdentifier *)&A->Oid,
  429. (AsnObjectIdentifier *)&B->Oid );
  430. } // MIB_sess_cmp
  431. //
  432. // None.
  433. //
  434. BOOL build_sess_entry_oids(
  435. )
  436. {
  437. AsnOctetString OSA ;
  438. AsnObjectIdentifier UserNameOid ;
  439. SESS_ENTRY *SessEntry ;
  440. unsigned i;
  441. // start pointer at 1st guy in the table
  442. SessEntry = MIB_SessionTable.Table ;
  443. // now iterate over the table, creating an oid for each entry
  444. for( i=0; i<MIB_SessionTable.Len ; i++) {
  445. // for each entry in the session table
  446. // copy the client name into the oid buffer first
  447. if (! MakeOidFromStr( &SessEntry->svSesClientName, &SessEntry->Oid ))
  448. {
  449. return FALSE;
  450. }
  451. // copy the user name into a temporary oid buffer
  452. if (! MakeOidFromStr( &SessEntry->svSesUserName, &UserNameOid ))
  453. {
  454. return FALSE;
  455. }
  456. // append the two entries forming the index
  457. if (! SnmpUtilOidAppend( &SessEntry->Oid, &UserNameOid ))
  458. {
  459. SnmpUtilOidFree( &UserNameOid );
  460. return FALSE;
  461. }
  462. // free the temporary buffer
  463. SnmpUtilOidFree( &UserNameOid );
  464. SessEntry++; // point to the next guy in the table
  465. } // for
  466. return TRUE;
  467. } // build_sess_entry_oids
  468. void FreeSessTable()
  469. {
  470. UINT i;
  471. SESS_ENTRY *MIB_SessionTableElement ;
  472. MIB_SessionTableElement = MIB_SessionTable.Table ;
  473. if (MIB_SessionTableElement)
  474. {
  475. // iterate over the whole table
  476. for(i=0; i<MIB_SessionTable.Len ;i++)
  477. {
  478. // free any alloc'ed elements of the structure
  479. SnmpUtilOidFree(&(MIB_SessionTableElement->Oid));
  480. SnmpUtilMemFree(MIB_SessionTableElement->svSesClientName.stream);
  481. SnmpUtilMemFree(MIB_SessionTableElement->svSesUserName.stream);
  482. MIB_SessionTableElement ++ ; // increment table entry
  483. }
  484. SnmpUtilMemFree(MIB_SessionTable.Table) ; // free the base Table
  485. }
  486. MIB_SessionTable.Table = NULL ; // just for safety
  487. MIB_SessionTable.Len = 0 ; // just for safety
  488. }
  489. //-------------------------------- END --------------------------------------